diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/event/EventService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/event/EventService.kt index ff4ea05f..604b631b 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/event/EventService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/event/EventService.kt @@ -228,7 +228,7 @@ class EventService( ) } - if (event.link != link) { + if (link != null && event.link != link) { event.link = link } @@ -240,7 +240,7 @@ class EventService( event.isPopup = isPopup } - if (isAdult != event.isAdult) { + if (isAdult != null && isAdult != event.isAdult) { event.isAdult = isAdult } diff --git a/src/test/kotlin/kr/co/vividnext/sodalive/event/EventControllerIntegrationTest.kt b/src/test/kotlin/kr/co/vividnext/sodalive/event/EventControllerIntegrationTest.kt index 98f20c63..79845357 100644 --- a/src/test/kotlin/kr/co/vividnext/sodalive/event/EventControllerIntegrationTest.kt +++ b/src/test/kotlin/kr/co/vividnext/sodalive/event/EventControllerIntegrationTest.kt @@ -5,19 +5,25 @@ import kr.co.vividnext.sodalive.i18n.Lang import kr.co.vividnext.sodalive.member.Member import kr.co.vividnext.sodalive.member.MemberAdapter import kr.co.vividnext.sodalive.support.EmbeddedRedisInitializer +import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.Test +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.NullSource +import org.junit.jupiter.params.provider.ValueSource import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc import org.springframework.boot.test.context.SpringBootTest import org.springframework.boot.test.mock.mockito.MockBean import org.springframework.security.authentication.UsernamePasswordAuthenticationToken import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.authentication +import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user import org.springframework.test.annotation.DirtiesContext import org.springframework.test.context.ContextConfiguration import org.springframework.test.web.servlet.MockMvc import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put import org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status import java.time.LocalDateTime @@ -108,6 +114,70 @@ class EventControllerIntegrationTest @Autowired constructor( .andExpect(status().isUnauthorized) } + @ParameterizedTest + @NullSource + @ValueSource(booleans = [true, false]) + @DisplayName("이벤트 제목만 수정하면 생략한 링크와 성인 여부 등 나머지 필드를 보존한다") + fun shouldPreserveOmittedFieldsWhenUpdatingOnlyTitle(isAdult: Boolean?) { + val event = saveEventForUpdate(isAdult) + + mockMvc.perform(updateRequest(event).param("title", "updated")) + .andExpect(status().isOk) + .andExpect(jsonPath("$.success").value(true)) + + assertEquals(event.copy(title = "updated"), eventRepository.findById(requireNotNull(event.id)).orElseThrow()) + } + + @ParameterizedTest + @ValueSource(booleans = [true, false]) + @DisplayName("이벤트 수정은 명시한 링크와 성인 여부를 저장한다") + fun shouldPersistExplicitLinkAndAdultFlag(isAdult: Boolean) { + val event = saveEventForUpdate(!isAdult) + + mockMvc.perform( + updateRequest(event) + .param("link", "https://event.test/updated") + .param("isAdult", isAdult.toString()) + ) + .andExpect(status().isOk) + .andExpect(jsonPath("$.success").value(true)) + + assertEquals( + event.copy(link = "https://event.test/updated", isAdult = isAdult), + eventRepository.findById(requireNotNull(event.id)).orElseThrow() + ) + } + + @ParameterizedTest + @ValueSource(strings = ["", " "]) + @DisplayName("이벤트 수정은 빈 링크 원문을 저장하고 생략한 성인 여부를 보존한다") + fun shouldPersistBlankLinkWithoutChangingOmittedAdultFlag(link: String) { + val event = saveEventForUpdate() + + mockMvc.perform(updateRequest(event).param("link", link)) + .andExpect(status().isOk) + .andExpect(jsonPath("$.success").value(true)) + + assertEquals(event.copy(link = link), eventRepository.findById(requireNotNull(event.id)).orElseThrow()) + } + + private fun updateRequest(event: Event) = + put("/event") + .param("id", event.id.toString()) + .with(user("admin").roles("ADMIN")) + + private fun saveEventForUpdate(isAdult: Boolean? = true): Event { + return eventRepository.saveAndFlush( + saveControllerEvent("original", Lang.EN).apply { + link = "https://event.test/original" + this.isAdult = isAdult + isActive = false + startDate = LocalDateTime.of(2099, 1, 1, 0, 0, 0) + endDate = LocalDateTime.of(2099, 1, 2, 23, 59, 59) + } + ) + } + private fun saveControllerEvent(seed: String, lang: Lang): Event { return eventRepository.saveAndFlush( Event(