diff --git a/backend/src/test/kotlin/com/condado/newsletter/controller/DispatchLogControllerTest.kt b/backend/src/test/kotlin/com/condado/newsletter/controller/DispatchLogControllerTest.kt new file mode 100644 index 0000000..87548f2 --- /dev/null +++ b/backend/src/test/kotlin/com/condado/newsletter/controller/DispatchLogControllerTest.kt @@ -0,0 +1,82 @@ +package com.condado.newsletter.controller + +import com.condado.newsletter.model.DispatchLog +import com.condado.newsletter.model.DispatchStatus +import com.condado.newsletter.model.VirtualEntity +import com.condado.newsletter.repository.DispatchLogRepository +import com.condado.newsletter.repository.VirtualEntityRepository +import com.condado.newsletter.scheduler.EntityScheduler +import com.ninjasquad.springmockk.MockkBean +import org.junit.jupiter.api.AfterEach +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.boot.test.context.SpringBootTest +import org.springframework.test.web.servlet.MockMvc +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get +import org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath +import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status + +@SpringBootTest +@AutoConfigureMockMvc +class DispatchLogControllerTest { + + @Autowired + lateinit var mockMvc: MockMvc + + @Autowired + lateinit var virtualEntityRepository: VirtualEntityRepository + + @Autowired + lateinit var dispatchLogRepository: DispatchLogRepository + + @MockkBean + lateinit var entityScheduler: EntityScheduler + + @AfterEach + fun cleanUp() { + dispatchLogRepository.deleteAll() + virtualEntityRepository.deleteAll() + } + + @Test + fun should_return200AndAllLogs_when_getAllLogs() { + val entity = virtualEntityRepository.save(VirtualEntity( + name = "Log Entity", + email = "log@condado.com", + jobTitle = "Logger" + )) + dispatchLogRepository.save(DispatchLog( + virtualEntity = entity, + emailSubject = "Test Subject", + status = DispatchStatus.SENT + )) + + mockMvc.perform(get("/api/v1/dispatch-logs")) + .andExpect(status().isOk) + .andExpect(jsonPath("$").isArray) + .andExpect(jsonPath("$[0].emailSubject").value("Test Subject")) + } + + @Test + fun should_return200AndFilteredLogs_when_getByEntityId() { + val entity1 = virtualEntityRepository.save(VirtualEntity( + name = "Entity One", + email = "one@condado.com", + jobTitle = "Job One" + )) + val entity2 = virtualEntityRepository.save(VirtualEntity( + name = "Entity Two", + email = "two@condado.com", + jobTitle = "Job Two" + )) + dispatchLogRepository.save(DispatchLog(virtualEntity = entity1, emailSubject = "Log One", status = DispatchStatus.SENT)) + dispatchLogRepository.save(DispatchLog(virtualEntity = entity2, emailSubject = "Log Two", status = DispatchStatus.FAILED)) + + mockMvc.perform(get("/api/v1/dispatch-logs/entity/${entity1.id}")) + .andExpect(status().isOk) + .andExpect(jsonPath("$").isArray) + .andExpect(jsonPath("$.length()").value(1)) + .andExpect(jsonPath("$[0].emailSubject").value("Log One")) + } +} diff --git a/backend/src/test/kotlin/com/condado/newsletter/controller/VirtualEntityControllerTest.kt b/backend/src/test/kotlin/com/condado/newsletter/controller/VirtualEntityControllerTest.kt new file mode 100644 index 0000000..9ec9aa8 --- /dev/null +++ b/backend/src/test/kotlin/com/condado/newsletter/controller/VirtualEntityControllerTest.kt @@ -0,0 +1,161 @@ +package com.condado.newsletter.controller + +import com.condado.newsletter.model.VirtualEntity +import com.condado.newsletter.repository.VirtualEntityRepository +import com.condado.newsletter.scheduler.EntityScheduler +import com.fasterxml.jackson.databind.ObjectMapper +import com.ninjasquad.springmockk.MockkBean +import io.mockk.every +import io.mockk.just +import io.mockk.runs +import io.mockk.verify +import org.junit.jupiter.api.AfterEach +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.boot.test.context.SpringBootTest +import org.springframework.http.MediaType +import org.springframework.test.web.servlet.MockMvc +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post +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 + +@SpringBootTest +@AutoConfigureMockMvc +class VirtualEntityControllerTest { + + @Autowired + lateinit var mockMvc: MockMvc + + @Autowired + lateinit var virtualEntityRepository: VirtualEntityRepository + + @MockkBean + lateinit var entityScheduler: EntityScheduler + + private val objectMapper = ObjectMapper() + + @AfterEach + fun cleanUp() { + virtualEntityRepository.deleteAll() + } + + @Test + fun should_return201AndBody_when_postWithValidPayload() { + val payload = mapOf( + "name" to "Fulano da Silva", + "email" to "fulano@condado.com", + "jobTitle" to "Diretor de Nada" + ) + + mockMvc.perform( + post("/api/v1/virtual-entities") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(payload)) + ) + .andExpect(status().isCreated) + .andExpect(jsonPath("$.name").value("Fulano da Silva")) + .andExpect(jsonPath("$.email").value("fulano@condado.com")) + .andExpect(jsonPath("$.jobTitle").value("Diretor de Nada")) + .andExpect(jsonPath("$.id").isNotEmpty) + } + + @Test + fun should_return400_when_postWithMissingRequiredField() { + val payload = mapOf("name" to "Fulano") // missing email and jobTitle + + mockMvc.perform( + post("/api/v1/virtual-entities") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(payload)) + ) + .andExpect(status().isBadRequest) + } + + @Test + fun should_return200AndList_when_getAllEntities() { + virtualEntityRepository.save(VirtualEntity( + name = "Test Entity", + email = "test@condado.com", + jobTitle = "Tester" + )) + + mockMvc.perform(get("/api/v1/virtual-entities")) + .andExpect(status().isOk) + .andExpect(jsonPath("$").isArray) + .andExpect(jsonPath("$[0].name").value("Test Entity")) + } + + @Test + fun should_return200AndEntity_when_getById() { + val entity = virtualEntityRepository.save(VirtualEntity( + name = "Test Entity", + email = "entity@condado.com", + jobTitle = "Test Job" + )) + + mockMvc.perform(get("/api/v1/virtual-entities/${entity.id}")) + .andExpect(status().isOk) + .andExpect(jsonPath("$.name").value("Test Entity")) + } + + @Test + fun should_return404_when_getByIdNotFound() { + val randomId = java.util.UUID.randomUUID() + + mockMvc.perform(get("/api/v1/virtual-entities/$randomId")) + .andExpect(status().isNotFound) + } + + @Test + fun should_return200_when_putWithValidPayload() { + val entity = virtualEntityRepository.save(VirtualEntity( + name = "Old Name", + email = "old@condado.com", + jobTitle = "Old Job" + )) + + val payload = mapOf("name" to "New Name") + + mockMvc.perform( + put("/api/v1/virtual-entities/${entity.id}") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(payload)) + ) + .andExpect(status().isOk) + .andExpect(jsonPath("$.name").value("New Name")) + .andExpect(jsonPath("$.email").value("old@condado.com")) + } + + @Test + fun should_return200AndDeactivated_when_delete() { + val entity = virtualEntityRepository.save(VirtualEntity( + name = "Active Entity", + email = "active@condado.com", + jobTitle = "Active Job" + )) + + mockMvc.perform(delete("/api/v1/virtual-entities/${entity.id}")) + .andExpect(status().isOk) + .andExpect(jsonPath("$.active").value(false)) + } + + @Test + fun should_return200_when_triggerEndpointCalled() { + val entity = virtualEntityRepository.save(VirtualEntity( + name = "Trigger Entity", + email = "trigger@condado.com", + jobTitle = "Trigger Job" + )) + + every { entityScheduler.runPipeline(any()) } just runs + + mockMvc.perform(post("/api/v1/virtual-entities/${entity.id}/trigger")) + .andExpect(status().isOk) + + verify(exactly = 1) { entityScheduler.runPipeline(any()) } + } +}