package roomescape.auth.infrastructure.jwt import io.jsonwebtoken.Jwts import io.jsonwebtoken.SignatureAlgorithm import io.kotest.assertions.throwables.shouldThrow import io.kotest.core.spec.style.FunSpec import io.kotest.matchers.shouldBe import roomescape.auth.exception.AuthErrorCode import roomescape.auth.exception.AuthException import roomescape.util.JwtFixture import java.util.* import kotlin.random.Random class JwtHandlerTest : FunSpec({ context("JWT 토큰 조회") { val memberId = Random.nextLong() val jwtHandler: JwtHandler = JwtFixture.create() test("토큰에서 멤버 ID를 올바르게 추출한다.") { val token = jwtHandler.createToken(memberId) val extractedMemberId = jwtHandler.getMemberIdFromToken(token) extractedMemberId shouldBe memberId } test("만료된 토큰이면 예외를 던진다.") { // given val expirationTime = 0L val shortExpirationTimeJwtHandler: JwtHandler = JwtFixture.create(expirationTime = expirationTime) val token = shortExpirationTimeJwtHandler.createToken(memberId) Thread.sleep(expirationTime) // 만료 시간 이후로 대기 // when & then shouldThrow { shortExpirationTimeJwtHandler.getMemberIdFromToken(token) }.errorCode shouldBe AuthErrorCode.EXPIRED_TOKEN } test("토큰이 빈 값이면 예외를 던진다.") { shouldThrow { jwtHandler.getMemberIdFromToken("") }.errorCode shouldBe AuthErrorCode.INVALID_TOKEN } test("시크릿 키가 잘못된 경우 예외를 던진다.") { val now: Date = Date() val invalidSignatureToken: String = Jwts.builder() .claim("memberId", memberId) .setIssuedAt(now) .setExpiration(Date(now.time + JwtFixture.EXPIRATION_TIME)) .signWith(SignatureAlgorithm.HS256, JwtFixture.SECRET_KEY.substring(1).toByteArray()) .compact() shouldThrow { jwtHandler.getMemberIdFromToken(invalidSignatureToken) }.errorCode shouldBe AuthErrorCode.INVALID_TOKEN } } })