From c9aaeab6650c147624d3b18705c9963d517a72bb Mon Sep 17 00:00:00 2001 From: Dave the Dev Date: Mon, 6 Jul 2026 00:07:50 +0000 Subject: [PATCH] test(portainer-automation): add DeployController tests --- .../controller/DeployControllerTest.java | 89 +++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 portainer-automation/src/test/java/com/hithomelabs/portainer/controller/DeployControllerTest.java diff --git a/portainer-automation/src/test/java/com/hithomelabs/portainer/controller/DeployControllerTest.java b/portainer-automation/src/test/java/com/hithomelabs/portainer/controller/DeployControllerTest.java new file mode 100644 index 0000000..14c9e69 --- /dev/null +++ b/portainer-automation/src/test/java/com/hithomelabs/portainer/controller/DeployControllerTest.java @@ -0,0 +1,89 @@ +package com.hithomelabs.portainer.controller; + +import com.hithomelabs.portainer.config.PortainerAutomationProperties; +import com.hithomelabs.portainer.service.DeployService; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; + +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +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.status; + +@ExtendWith(MockitoExtension.class) +class DeployControllerTest { + + @Mock + private DeployService deployService; + + @Mock + private PortainerAutomationProperties properties; + + @Mock + private PortainerAutomationProperties.Service serviceProps; + + @InjectMocks + private DeployController controller; + + private MockMvc mockMvc; + + private static final String VALID_API_KEY = "valid-key"; + private static final Long STACK_ID = 42L; + + @BeforeEach + void setUp() { + mockMvc = MockMvcBuilders.standaloneSetup(controller).build(); + when(properties.getService()).thenReturn(serviceProps); + when(serviceProps.getApiKey()).thenReturn(VALID_API_KEY); + } + + @Test + void deploy_withValidKey_returnsOk() throws Exception { + mockMvc.perform(post("/api/deploy/{stackId}", STACK_ID) + .header("X-API-Key", VALID_API_KEY) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(content().string("Stack " + STACK_ID + " redeploy triggered")); + + verify(deployService).deploy(STACK_ID); + } + + @Test + void deploy_withInvalidKey_returnsUnauthorized() throws Exception { + mockMvc.perform(post("/api/deploy/{stackId}", STACK_ID) + .header("X-API-Key", "wrong-key") + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isUnauthorized()) + .andExpect(content().string("Invalid or missing X-API-Key")); + } + + @Test + void deploy_withoutKey_returnsUnauthorized() throws Exception { + mockMvc.perform(post("/api/deploy/{stackId}", STACK_ID) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isUnauthorized()) + .andExpect(content().string("Invalid or missing X-API-Key")); + } + + @Test + void deploy_whenServiceThrows_returnsInternalServerError() throws Exception { + doThrow(new RuntimeException("Portainer unreachable")) + .when(deployService).deploy(STACK_ID); + + mockMvc.perform(post("/api/deploy/{stackId}", STACK_ID) + .header("X-API-Key", VALID_API_KEY) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isInternalServerError()) + .andExpect(content().string("Redeploy failed: Portainer unreachable")); + } +}