package kr.itn.itnhub.contact; import kr.itn.itnhub.AbstractDbTest; import kr.itn.itnhub.org.Organization; import kr.itn.itnhub.org.OrganizationMapper; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.http.MediaType; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.security.test.context.support.WithMockUser; import org.springframework.test.web.servlet.MockMvc; import static org.assertj.core.api.Assertions.assertThat; import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; 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.request.MockMvcRequestBuilders.put; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @AutoConfigureMockMvc @WithMockUser(roles = "ADMIN") class ContactControllerTest extends AbstractDbTest { @Autowired MockMvc mvc; @Autowired ContactMapper contactMapper; @Autowired OrganizationMapper orgMapper; @Autowired JdbcTemplate jdbc; @BeforeEach void clean() { jdbc.update("delete from organization"); jdbc.update("delete from contact"); } @Test void 담당자를_등록하면_저장된_값을_돌려준다() throws Exception { mvc.perform(post("/api/contacts") .with(csrf()) .contentType(MediaType.APPLICATION_JSON) .content(""" { "category": "APPLICANT", "name": "송민지", "affiliation": "국제방송교류재단", "deptName": "데이터정보화팀", "title": "과장", "phone": "02-3475-5434", "email": "ming@arirang.com" } """)) .andExpect(status().isOk()) .andExpect(jsonPath("$.category").value("APPLICANT")) .andExpect(jsonPath("$.name").value("송민지")) .andExpect(jsonPath("$.affiliation").value("국제방송교류재단")) .andExpect(jsonPath("$.id").isNumber()); assertThat(contactMapper.findAll(null)).hasSize(1); } @Test void 구분_필터로_목록을_조회한다() throws Exception { Contact applicant = new Contact(); applicant.setCategory("APPLICANT"); applicant.setName("송민지"); contactMapper.insert(applicant); Contact lawyer = new Contact(); lawyer.setCategory("LAWYER"); lawyer.setName("이변호"); contactMapper.insert(lawyer); mvc.perform(get("/api/contacts").param("category", "LAWYER")) .andExpect(status().isOk()) .andExpect(jsonPath("$.length()").value(1)) .andExpect(jsonPath("$[0].name").value("이변호")); mvc.perform(get("/api/contacts")) .andExpect(status().isOk()) .andExpect(jsonPath("$.length()").value(2)); } @Test void 구분값이_잘못되면_등록시_400이다() throws Exception { mvc.perform(post("/api/contacts") .with(csrf()) .contentType(MediaType.APPLICATION_JSON) .content(""" { "category": "UNKNOWN", "name": "홍길동" } """)) .andExpect(status().isBadRequest()); } @Test void 성명이_비면_등록시_400이다() throws Exception { mvc.perform(post("/api/contacts") .with(csrf()) .contentType(MediaType.APPLICATION_JSON) .content(""" { "category": "APPLICANT", "name": "" } """)) .andExpect(status().isBadRequest()) .andExpect(jsonPath("$.message").value(org.hamcrest.Matchers.containsString("성명"))); } @Test void 담당자를_수정하면_변경된_값이_저장된다() throws Exception { Contact contact = new Contact(); contact.setCategory("MJ"); contact.setName("김문정"); contactMapper.insert(contact); mvc.perform(put("/api/contacts/{id}", contact.getId()) .with(csrf()) .contentType(MediaType.APPLICATION_JSON) .content(""" { "category": "MJ", "name": "김문정", "phone": "02-1234-5678", "email": "mj@mcst.go.kr" } """)) .andExpect(status().isOk()) .andExpect(jsonPath("$.phone").value("02-1234-5678")) .andExpect(jsonPath("$.email").value("mj@mcst.go.kr")); } @Test void 존재하지_않는_담당자를_수정하면_404다() throws Exception { mvc.perform(put("/api/contacts/{id}", 999999) .with(csrf()) .contentType(MediaType.APPLICATION_JSON) .content(""" { "category": "MJ", "name": "김문정" } """)) .andExpect(status().isNotFound()); } @Test void 존재하지_않는_담당자를_삭제하면_404다() throws Exception { mvc.perform(delete("/api/contacts/{id}", 999999).with(csrf())) .andExpect(status().isNotFound()); } @Test void 담당자를_삭제하면_배정되어_있던_기관의_배정도_함께_해제된다() throws Exception { Contact contact = new Contact(); contact.setCategory("APPLICANT"); contact.setName("송민지"); contactMapper.insert(contact); Organization org = new Organization(); org.setOrgNo("001"); org.setOrgName("국제방송교류재단"); org.setChannelSlug("001"); orgMapper.upsertBySeed(org); Long orgId = orgMapper.findAll().get(0).getId(); orgMapper.updateAssignments(orgId, contact.getId(), null, null, null); assertThat(orgMapper.findById(orgId).getStatus().name()).isEqualTo("READY"); mvc.perform(delete("/api/contacts/{id}", contact.getId()).with(csrf())) .andExpect(status().isNoContent()); assertThat(contactMapper.findById(contact.getId())).isNull(); Organization after = orgMapper.findById(orgId); assertThat(after.getApplicantContactId()).isNull(); assertThat(after.getStatus().name()).isEqualTo("INFO_PENDING"); } }