package com.vaessl.app.connection; import static com.vaessl.app.Mockdata.*; import static com.vaessl.app.connection.Endpoint.*; import static com.vaessl.app.connection.ServiceType.*; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; import com.github.tomakehurst.wiremock.client.WireMock; import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo; import com.github.tomakehurst.wiremock.junit5.WireMockTest; import jakarta.servlet.http.Cookie; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.webmvc.test.autoconfigure.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.MvcResult; @SpringBootTest @AutoConfigureMockMvc @WireMockTest class ConnectionControllerTest { @Autowired MockMvc mockMvc; private static final String LOGIN_PATH = LOGIN.getValue(); private static final String STATUS_PATH = CONNECTION_STATUS.getValue(); private static final String LOGOUT_PATH = "/connections/HOMEBOX"; private static final String VALID_HOMEBOX_RESPONSE = """ { "token": "fake-jwt-token", "attachmentToken": "fake-attach", "expiresAt": "2099-01-01T00:00:00Z" } """; private static final String EXPIRED_HOMEBOX_RESPONSE = """ { "token": "expired-token", "attachmentToken": "fake-attach", "expiresAt": "2000-01-01T00:00:00Z" } """; @Test void shouldReturnEmptyListWhenNoActiveSession() throws Exception { mockMvc.perform(get(STATUS_PATH)).andExpect(status().isOk()) .andExpect(content().json("[]")); } @Test void shouldReturnConnectionStatusWithConnectedTrueAfterLogin(WireMockRuntimeInfo wm) throws Exception { WireMock.stubFor(WireMock.post(HOMEBOX_LOGIN.getValue()) .willReturn(WireMock.okJson(VALID_HOMEBOX_RESPONSE))); MvcResult loginResult = mockMvc .perform(post(LOGIN_PATH).contentType(MediaType.APPLICATION_JSON) .content(connectionRequestBody(wm))) .andExpect(status().isOk()).andReturn(); Cookie sessionCookie = loginResult.getResponse().getCookie("SESSION"); mockMvc.perform(get(STATUS_PATH).cookie(sessionCookie)).andExpect(status().isOk()) .andExpect(jsonPath("$.length()").value(1)) .andExpect(jsonPath("$[0].serviceType").value(HOMEBOX.getValue())) .andExpect(jsonPath("$[0].username").value(MOCK_USER)) .andExpect(jsonPath("$[0].appUrl").value(wm.getHttpBaseUrl())) .andExpect(jsonPath("$[0].connected").value(true)); } @Test void shouldReturnConnectedFalseWhenStoredTokenIsExpired(WireMockRuntimeInfo wm) throws Exception { WireMock.stubFor(WireMock.post(HOMEBOX_LOGIN.getValue()) .willReturn(WireMock.okJson(EXPIRED_HOMEBOX_RESPONSE))); MvcResult loginResult = mockMvc .perform(post(LOGIN_PATH).contentType(MediaType.APPLICATION_JSON) .content(connectionRequestBody(wm))) .andExpect(status().isOk()).andReturn(); Cookie sessionCookie = loginResult.getResponse().getCookie("SESSION"); mockMvc.perform(get(STATUS_PATH).cookie(sessionCookie)).andExpect(status().isOk()) .andExpect(jsonPath("$[0].serviceType").value(HOMEBOX.getValue())) .andExpect(jsonPath("$[0].connected").value(false)) .andExpect(jsonPath("$[0].expiresAt") .value("2000-01-01T00:00:00Z")); } @Test void shouldReturn204NoContentOnLogout(WireMockRuntimeInfo wm) throws Exception { WireMock.stubFor(WireMock.post(HOMEBOX_LOGIN.getValue()) .willReturn(WireMock.okJson(VALID_HOMEBOX_RESPONSE))); MvcResult loginResult = mockMvc .perform(post(LOGIN_PATH).contentType(MediaType.APPLICATION_JSON) .content(connectionRequestBody(wm))) .andExpect(status().isOk()).andReturn(); Cookie sessionCookie = loginResult.getResponse().getCookie("SESSION"); mockMvc.perform(delete(LOGOUT_PATH).cookie(sessionCookie)) .andExpect(status().isNoContent()); } @Test void shouldReturnEmptyStatusListAfterLogout(WireMockRuntimeInfo wm) throws Exception { WireMock.stubFor(WireMock.post(HOMEBOX_LOGIN.getValue()) .willReturn(WireMock.okJson(VALID_HOMEBOX_RESPONSE))); MvcResult loginResult = mockMvc .perform(post(LOGIN_PATH).contentType(MediaType.APPLICATION_JSON) .content(connectionRequestBody(wm))) .andExpect(status().isOk()).andReturn(); Cookie sessionCookie = loginResult.getResponse().getCookie("SESSION"); // Verify connected before logout mockMvc.perform(get(STATUS_PATH).cookie(sessionCookie)).andExpect(status().isOk()) .andExpect(jsonPath("$.length()").value(1)); mockMvc.perform(delete(LOGOUT_PATH).cookie(sessionCookie)) .andExpect(status().isNoContent()); // A new request (no session cookie, as in a fresh browser) returns no connections mockMvc.perform(get(STATUS_PATH)).andExpect(status().isOk()) .andExpect(content().json("[]")); } @Test void shouldReturn204WhenLogoutCalledWithNoActiveSession() throws Exception { mockMvc.perform(delete(LOGOUT_PATH)).andExpect(status().isNoContent()); } private String connectionRequestBody(WireMockRuntimeInfo wm) { return """ { "appUrl": "%s", "serviceType": "HOMEBOX", "username": "%s", "password": "%s" } """.formatted(wm.getHttpBaseUrl(), MOCK_USER, MOCK_PASS); } }