diff --git a/backend/src/test/kotlin/com/condado/newsletter/controller/AuthControllerTest.kt b/backend/src/test/kotlin/com/condado/newsletter/controller/AuthControllerTest.kt new file mode 100644 index 0000000..03dd275 --- /dev/null +++ b/backend/src/test/kotlin/com/condado/newsletter/controller/AuthControllerTest.kt @@ -0,0 +1,76 @@ +package com.condado.newsletter.controller + +import com.condado.newsletter.scheduler.EntityScheduler +import com.condado.newsletter.service.JwtService +import com.ninjasquad.springmockk.MockkBean +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.get +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post +import org.springframework.test.web.servlet.result.MockMvcResultMatchers.cookie +import org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath +import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status +import jakarta.servlet.http.Cookie + +@SpringBootTest +@AutoConfigureMockMvc +class AuthControllerTest { + + @Autowired + lateinit var mockMvc: MockMvc + + @Autowired + lateinit var jwtService: JwtService + + @MockkBean + lateinit var entityScheduler: EntityScheduler + + @Test + fun should_return200AndSetCookie_when_correctPasswordPosted() { + mockMvc.perform( + post("/api/auth/login") + .contentType(MediaType.APPLICATION_JSON) + .content("""{"password":"testpassword"}""") + ) + .andExpect(status().isOk) + .andExpect(cookie().exists("jwt")) + .andExpect(cookie().httpOnly("jwt", true)) + } + + @Test + fun should_return401_when_wrongPasswordPosted() { + mockMvc.perform( + post("/api/auth/login") + .contentType(MediaType.APPLICATION_JSON) + .content("""{"password":"wrongpassword"}""") + ) + .andExpect(status().isUnauthorized) + } + + @Test + fun should_return200_when_getMeWithValidCookie() { + val token = jwtService.generateToken() + + mockMvc.perform( + get("/api/auth/me") + .cookie(Cookie("jwt", token)) + ) + .andExpect(status().isOk) + } + + @Test + fun should_return401_when_getMeWithNoCookie() { + mockMvc.perform(get("/api/auth/me")) + .andExpect(status().isUnauthorized) + } + + @Test + fun should_return401_when_protectedEndpointAccessedWithoutCookie() { + mockMvc.perform(get("/api/v1/virtual-entities")) + .andExpect(status().isUnauthorized) + } +} diff --git a/backend/src/test/kotlin/com/condado/newsletter/service/AuthServiceTest.kt b/backend/src/test/kotlin/com/condado/newsletter/service/AuthServiceTest.kt new file mode 100644 index 0000000..d1e6305 --- /dev/null +++ b/backend/src/test/kotlin/com/condado/newsletter/service/AuthServiceTest.kt @@ -0,0 +1,62 @@ +package com.condado.newsletter.service + +import io.mockk.every +import io.mockk.mockk +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows + +class AuthServiceTest { + + private val jwtService: JwtService = mockk() + private lateinit var authService: AuthService + + @BeforeEach + fun setUp() { + authService = AuthService( + jwtService = jwtService, + appPassword = "testpassword" + ) + } + + @Test + fun should_returnJwtToken_when_correctPasswordProvided() { + every { jwtService.generateToken() } returns "jwt-token" + + val token = authService.login("testpassword") + + assertThat(token).isEqualTo("jwt-token") + } + + @Test + fun should_throwUnauthorizedException_when_wrongPasswordProvided() { + assertThrows { + authService.login("wrongpassword") + } + } + + @Test + fun should_returnValidClaims_when_jwtTokenParsed() { + val realJwtService = JwtService( + secret = "test-secret-key-for-testing-only-must-be-at-least-32-characters", + expirationMs = 86400000L + ) + val token = realJwtService.generateToken() + + assertThat(realJwtService.validateToken(token)).isTrue() + } + + @Test + fun should_returnFalse_when_expiredTokenValidated() { + val realJwtService = JwtService( + secret = "test-secret-key-for-testing-only-must-be-at-least-32-characters", + expirationMs = 1L + ) + val token = realJwtService.generateToken() + + Thread.sleep(10) // wait for expiration + + assertThat(realJwtService.validateToken(token)).isFalse() + } +}