diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/event/banner/AdminEventBannerService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/event/banner/AdminEventBannerService.kt index 250fc4bd..eef0a186 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/admin/event/banner/AdminEventBannerService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/event/banner/AdminEventBannerService.kt @@ -167,7 +167,7 @@ class AdminEventBannerService( ) } - if (event.link != link) { + if (link != null && event.link != link) { event.link = if (link.isNullOrBlank()) null else link } @@ -179,7 +179,7 @@ class AdminEventBannerService( 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/admin/event/banner/AdminEventBannerControllerIntegrationTest.kt b/src/test/kotlin/kr/co/vividnext/sodalive/admin/event/banner/AdminEventBannerControllerIntegrationTest.kt index 154b545e..00424ca6 100644 --- a/src/test/kotlin/kr/co/vividnext/sodalive/admin/event/banner/AdminEventBannerControllerIntegrationTest.kt +++ b/src/test/kotlin/kr/co/vividnext/sodalive/admin/event/banner/AdminEventBannerControllerIntegrationTest.kt @@ -11,6 +11,9 @@ 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.mockito.Mockito import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc @@ -24,6 +27,7 @@ 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.multipart +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.io.InputStream @@ -117,6 +121,72 @@ class AdminEventBannerControllerIntegrationTest @Autowired constructor( .andExpect(jsonPath("$.data[*].lang").value(containsInAnyOrder("KO", "EN", "JA"))) } + @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("관리자 이벤트 수정은 빈 링크를 null로 저장하고 생략한 성인 여부를 보존한다") + fun shouldClearBlankLinkWithoutChangingOmittedAdultFlag(link: String) { + val event = saveEventForUpdate() + + mockMvc.perform(updateRequest(event).param("link", link)) + .andExpect(status().isOk) + .andExpect(jsonPath("$.success").value(true)) + + assertEquals(event.copy(link = null), eventRepository.findById(requireNotNull(event.id)).orElseThrow()) + } + + private fun updateRequest(event: Event) = + put("/admin/event/banner") + .param("id", event.id.toString()) + .with(user("admin").roles("ADMIN")) + + private fun saveEventForUpdate(isAdult: Boolean? = true): Event { + return eventRepository.saveAndFlush( + activeEvent("original", Lang.EN).apply { + popupImage = "original-popup.png" + link = "https://event.test/original" + this.isAdult = isAdult + isPopup = true + isActive = false + startDate = LocalDateTime.of(2099, 1, 1, 0, 0, 0) + endDate = LocalDateTime.of(2099, 1, 2, 23, 59, 59) + } + ) + } + private fun createRequest() = multipart("/admin/event/banner") .file(MockMultipartFile("thumbnail", "thumbnail.png", "image/png", "thumbnail".toByteArray()))