Fix failures in UserRouteTest
This commit is contained in:
parent
aa96cbbf3a
commit
4ae19c09c2
4 changed files with 126 additions and 170 deletions
|
@ -25,9 +25,15 @@ fun Application.userRoutes(
|
|||
post("/login") {
|
||||
val request = call.receive<LoginRequest>()
|
||||
val user =
|
||||
userRepository.findAll(nameOrEmail = request.username, password = passwordHasher.hash(request.password))
|
||||
userRepository.findAll(
|
||||
nameOrEmail = request.username,
|
||||
password = passwordHasher.hash(request.password)
|
||||
)
|
||||
.firstOrNull()
|
||||
?: userRepository.findAll(nameOrEmail = request.username, password = passwordHasher.hash(request.password))
|
||||
?: userRepository.findAll(
|
||||
nameOrEmail = request.username,
|
||||
password = passwordHasher.hash(request.password)
|
||||
)
|
||||
.firstOrNull()
|
||||
?: run {
|
||||
errorResponse(HttpStatusCode.Unauthorized, "Invalid credentials")
|
||||
|
@ -73,16 +79,18 @@ fun Application.userRoutes(
|
|||
authenticate(optional = false) {
|
||||
get {
|
||||
val query = call.request.queryParameters["query"]
|
||||
val budgetIds = call.request.queryParameters.getAll("budgetId")
|
||||
if (query != null) {
|
||||
if (query.isBlank()) {
|
||||
errorResponse(HttpStatusCode.BadRequest, "query cannot be empty")
|
||||
}
|
||||
call.respond(userRepository.findAll(nameLike = query).map { it.asResponse() })
|
||||
return@get
|
||||
} else if (budgetIds == null || budgetIds.all { it.isBlank() }) {
|
||||
errorResponse(HttpStatusCode.BadRequest, "query or budgetId required but absent")
|
||||
}
|
||||
permissionRepository.findAll(
|
||||
budgetIds = call.request.queryParameters.getAll("budgetId")
|
||||
).mapNotNull {
|
||||
permissionRepository.findAll(budgetIds = budgetIds)
|
||||
.mapNotNull {
|
||||
userRepository.findAll(ids = listOf(it.userId))
|
||||
.firstOrNull()
|
||||
?.asResponse()
|
||||
|
|
|
@ -4,8 +4,8 @@ import com.wbrawner.twigs.ErrorResponse
|
|||
import com.wbrawner.twigs.PasswordResetRequest
|
||||
import com.wbrawner.twigs.ResetPasswordRequest
|
||||
import com.wbrawner.twigs.model.PasswordResetToken
|
||||
import com.wbrawner.twigs.model.User
|
||||
import com.wbrawner.twigs.randomString
|
||||
import com.wbrawner.twigs.test.helpers.repository.FakeUserRepository.Companion.TEST_USER
|
||||
import io.ktor.client.call.*
|
||||
import io.ktor.client.request.*
|
||||
import io.ktor.http.*
|
||||
|
@ -17,7 +17,7 @@ import java.util.*
|
|||
class PasswordResetRouteTest : ApiTest() {
|
||||
@Test
|
||||
fun `reset password with invalid username returns 202`() = apiTest { client ->
|
||||
val request = ResetPasswordRequest(username = "testuser")
|
||||
val request = ResetPasswordRequest(username = "invaliduser")
|
||||
val response = client.post("/api/resetpassword") {
|
||||
header("Content-Type", "application/json")
|
||||
setBody(request)
|
||||
|
@ -28,14 +28,6 @@ class PasswordResetRouteTest : ApiTest() {
|
|||
|
||||
@Test
|
||||
fun `reset password with valid username returns 202`() = apiTest { client ->
|
||||
val users = listOf(
|
||||
User(
|
||||
name = "testuser",
|
||||
email = "test@example.com",
|
||||
password = "\$2a\$10\$bETxbFPja1PyXVLybETxb.CWBYzyYdZpmCcA7NSIN8dkdzidt1Xv2"
|
||||
),
|
||||
)
|
||||
users.forEach { userRepository.save(it) }
|
||||
val request = ResetPasswordRequest(username = "testuser")
|
||||
val response = client.post("/api/resetpassword") {
|
||||
header("Content-Type", "application/json")
|
||||
|
@ -44,10 +36,10 @@ class PasswordResetRouteTest : ApiTest() {
|
|||
assertEquals(HttpStatusCode.Accepted, response.status)
|
||||
assertEquals(1, emailService.emails.size)
|
||||
val email = emailService.emails.first()
|
||||
assertEquals(users.first().email, email.to)
|
||||
assertEquals(TEST_USER.email, email.to)
|
||||
assertEquals(1, passwordResetRepository.entities.size)
|
||||
val passwordReset = passwordResetRepository.entities.first()
|
||||
assertEquals(users.first().id, passwordReset.userId)
|
||||
assertEquals(TEST_USER.id, passwordReset.userId)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -77,11 +69,7 @@ class PasswordResetRouteTest : ApiTest() {
|
|||
|
||||
@Test
|
||||
fun `password reset with valid token returns 200`() = apiTest { client ->
|
||||
val users = listOf(
|
||||
User(name = "testuser", password = "\$2a\$10\$bETxbFPja1PyXVLybETxb.CWBYzyYdZpmCcA7NSIN8dkdzidt1Xv2"),
|
||||
)
|
||||
users.forEach { userRepository.save(it) }
|
||||
val token = passwordResetRepository.save(PasswordResetToken(userId = users.first().id))
|
||||
val token = passwordResetRepository.save(PasswordResetToken(userId = userRepository.findAll("testuser").first().id))
|
||||
val request = PasswordResetRequest(token = token.id, password = "newpass")
|
||||
val response = client.post("/api/passwordreset") {
|
||||
header("Content-Type", "application/json")
|
||||
|
@ -89,8 +77,8 @@ class PasswordResetRouteTest : ApiTest() {
|
|||
}
|
||||
assertEquals(HttpStatusCode.NoContent, response.status)
|
||||
assertEquals(
|
||||
"\$2a\$10\$bETxbFPja1PyXVLybETxb.E7dYGWCalFjrgd3ofAfKD8MqR0Ukua6",
|
||||
userRepository.entities.first().password
|
||||
"newpass",
|
||||
userRepository.findAll(TEST_USER.name).first().password
|
||||
)
|
||||
assert(passwordResetRepository.entities.isEmpty())
|
||||
}
|
||||
|
|
|
@ -3,10 +3,13 @@ package com.wbrawner.twigs.server.api
|
|||
import com.wbrawner.twigs.*
|
||||
import com.wbrawner.twigs.model.Session
|
||||
import com.wbrawner.twigs.model.User
|
||||
import com.wbrawner.twigs.test.helpers.repository.FakeUserRepository.Companion.OTHER_USER
|
||||
import com.wbrawner.twigs.test.helpers.repository.FakeUserRepository.Companion.TEST_USER
|
||||
import io.ktor.client.call.*
|
||||
import io.ktor.client.request.*
|
||||
import io.ktor.http.*
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.Assertions.assertNotNull
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
class UserRouteTest : ApiTest() {
|
||||
|
@ -36,11 +39,7 @@ class UserRouteTest : ApiTest() {
|
|||
|
||||
@Test
|
||||
fun `login with invalid password returns 401`() = apiTest { client ->
|
||||
val users = listOf(
|
||||
User(name = "testuser", password = "\$2a\$10\$bETxbFPja1PyXVLybETxb.CWBYzyYdZpmCcA7NSIN8dkdzidt1Xv2"),
|
||||
)
|
||||
users.forEach { userRepository.save(it) }
|
||||
val request = LoginRequest("testuser", "pass")
|
||||
val request = LoginRequest(TEST_USER.name, "pass")
|
||||
val response = client.post("/api/users/login") {
|
||||
header("Content-Type", "application/json")
|
||||
setBody(request)
|
||||
|
@ -52,11 +51,7 @@ class UserRouteTest : ApiTest() {
|
|||
|
||||
@Test
|
||||
fun `login with empty password returns 401`() = apiTest { client ->
|
||||
val users = listOf(
|
||||
User(name = "testuser", password = "\$2a\$10\$bETxbFPja1PyXVLybETxb.CWBYzyYdZpmCcA7NSIN8dkdzidt1Xv2"),
|
||||
)
|
||||
users.forEach { userRepository.save(it) }
|
||||
val request = LoginRequest("testuser", "")
|
||||
val request = LoginRequest(TEST_USER.name, "")
|
||||
val response = client.post("/api/users/login") {
|
||||
header("Content-Type", "application/json")
|
||||
setBody(request)
|
||||
|
@ -68,41 +63,27 @@ class UserRouteTest : ApiTest() {
|
|||
|
||||
@Test
|
||||
fun `login with valid username and password returns 200`() = apiTest { client ->
|
||||
val users = listOf(
|
||||
User(name = "testuser", password = "\$2a\$10\$bETxbFPja1PyXVLybETxb.CWBYzyYdZpmCcA7NSIN8dkdzidt1Xv2"),
|
||||
User(name = "otheruser", password = "\$2a\$10\$bETxbFPja1PyXVLybETxb..rhfIeOkP4qil1Drj29LDUhBxVkm6fS"),
|
||||
)
|
||||
users.forEach { userRepository.save(it) }
|
||||
val request = LoginRequest("testuser", "testpassword")
|
||||
val request = LoginRequest(TEST_USER.name, TEST_USER.password)
|
||||
val response = client.post("/api/users/login") {
|
||||
header("Content-Type", "application/json")
|
||||
setBody(request)
|
||||
}
|
||||
assertEquals(HttpStatusCode.OK, response.status)
|
||||
val session = response.body<SessionResponse>()
|
||||
assertEquals(users.first().id, session.userId)
|
||||
assertEquals(TEST_USER.id, session.userId)
|
||||
assert(session.token.isNotBlank())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `login with valid email and password returns 200`() = apiTest { client ->
|
||||
val users = listOf(
|
||||
User(
|
||||
name = "testuser",
|
||||
email = "test@example.com",
|
||||
password = "\$2a\$10\$bETxbFPja1PyXVLybETxb.CWBYzyYdZpmCcA7NSIN8dkdzidt1Xv2"
|
||||
),
|
||||
User(name = "otheruser", password = "\$2a\$10\$bETxbFPja1PyXVLybETxb..rhfIeOkP4qil1Drj29LDUhBxVkm6fS"),
|
||||
)
|
||||
users.forEach { userRepository.save(it) }
|
||||
val request = LoginRequest("test@example.com", "testpassword")
|
||||
val request = LoginRequest(TEST_USER.email, TEST_USER.password)
|
||||
val response = client.post("/api/users/login") {
|
||||
header("Content-Type", "application/json")
|
||||
setBody(request)
|
||||
}
|
||||
assertEquals(HttpStatusCode.OK, response.status)
|
||||
val session = response.body<SessionResponse>()
|
||||
assertEquals(users.first().id, session.userId)
|
||||
assertEquals(TEST_USER.id, session.userId)
|
||||
assert(session.token.isNotBlank())
|
||||
}
|
||||
|
||||
|
@ -156,15 +137,7 @@ class UserRouteTest : ApiTest() {
|
|||
|
||||
@Test
|
||||
fun `register with existing username returns 400`() = apiTest { client ->
|
||||
val users = listOf(
|
||||
User(
|
||||
name = "testuser",
|
||||
email = "test@example.com",
|
||||
password = "\$2a\$10\$bETxbFPja1PyXVLybETxb.CWBYzyYdZpmCcA7NSIN8dkdzidt1Xv2"
|
||||
),
|
||||
)
|
||||
users.forEach { userRepository.save(it) }
|
||||
val request = UserRequest(username = "testuser", password = "password")
|
||||
val request = UserRequest(username = TEST_USER.name, password = "password")
|
||||
val response = client.post("/api/users/register") {
|
||||
header("Content-Type", "application/json")
|
||||
setBody(request)
|
||||
|
@ -176,15 +149,7 @@ class UserRouteTest : ApiTest() {
|
|||
|
||||
@Test
|
||||
fun `register with existing email returns 400`() = apiTest { client ->
|
||||
val users = listOf(
|
||||
User(
|
||||
name = "testuser",
|
||||
email = "test@example.com",
|
||||
password = "\$2a\$10\$bETxbFPja1PyXVLybETxb.CWBYzyYdZpmCcA7NSIN8dkdzidt1Xv2"
|
||||
),
|
||||
)
|
||||
users.forEach { userRepository.save(it) }
|
||||
val request = UserRequest(username = "testuser2", email = "test@example.com", password = "password")
|
||||
val request = UserRequest(username = "testuser2", email = TEST_USER.email, password = "password")
|
||||
val response = client.post("/api/users/register") {
|
||||
header("Content-Type", "application/json")
|
||||
setBody(request)
|
||||
|
@ -196,7 +161,8 @@ class UserRouteTest : ApiTest() {
|
|||
|
||||
@Test
|
||||
fun `register with valid username and password returns 200`() = apiTest { client ->
|
||||
val request = UserRequest("testuser", "testpassword")
|
||||
val initialUserCount = userRepository.entities.size
|
||||
val request = UserRequest("newuser", "newpass")
|
||||
val response = client.post("/api/users/register") {
|
||||
header("Content-Type", "application/json")
|
||||
setBody(request)
|
||||
|
@ -206,12 +172,14 @@ class UserRouteTest : ApiTest() {
|
|||
assert(userResponse.id.isNotBlank())
|
||||
assertEquals(request.username, userResponse.username)
|
||||
assertEquals("", userResponse.email)
|
||||
assertEquals(1, userRepository.entities.size)
|
||||
val savedUser: User = userRepository.entities.first()
|
||||
assertEquals(initialUserCount + 1, userRepository.entities.size)
|
||||
val savedUser: User? = userRepository.findAll("newuser").firstOrNull()
|
||||
assertNotNull(savedUser)
|
||||
requireNotNull(savedUser)
|
||||
assertEquals(userResponse.id, savedUser.id)
|
||||
assertEquals(request.username, savedUser.name)
|
||||
assertEquals("", savedUser.email)
|
||||
assertEquals("\$2a\$10\$bETxbFPja1PyXVLybETxb.CWBYzyYdZpmCcA7NSIN8dkdzidt1Xv2", savedUser.password)
|
||||
assertEquals("newpass", savedUser.password)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -256,12 +224,7 @@ class UserRouteTest : ApiTest() {
|
|||
|
||||
@Test
|
||||
fun `get users with valid query and matches returns list`() = apiTest { client ->
|
||||
val users = listOf(
|
||||
User(name = "testuser", password = "testpassword"),
|
||||
User(name = "otheruser", password = "otherpassword"),
|
||||
)
|
||||
users.forEach { userRepository.save(it) }
|
||||
val session = Session(userId = users.first().id)
|
||||
val session = Session(userId = TEST_USER.id)
|
||||
sessionRepository.save(session)
|
||||
val response = client.get("/api/users?query=user") {
|
||||
header("Authorization", "Bearer ${session.token}")
|
||||
|
@ -269,25 +232,17 @@ class UserRouteTest : ApiTest() {
|
|||
assertEquals(HttpStatusCode.OK, response.status)
|
||||
val userQueryResponse: List<UserResponse> = response.body()
|
||||
assertEquals(2, userQueryResponse.size)
|
||||
repeat(2) { i ->
|
||||
assertEquals(users[i].id, userQueryResponse[i].id, "User IDs at index $i don't match")
|
||||
assertEquals(users[i].name, userQueryResponse[i].username, "Usernames at index $i don't match")
|
||||
assertEquals(users[i].email, userQueryResponse[i].email, "User emails at index $i don't match")
|
||||
}
|
||||
assertEquals(TEST_USER.asResponse(), userQueryResponse[0])
|
||||
assertEquals(OTHER_USER.asResponse(), userQueryResponse[1])
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `get users with empty budgetId returns 400`() = apiTest { client ->
|
||||
|
||||
val session = Session(userId = TEST_USER.id)
|
||||
sessionRepository.save(session)
|
||||
val response = client.get("/api/users?budgetId=") {
|
||||
header("Authorization", "Bearer ${session.token}")
|
||||
}
|
||||
assertEquals(HttpStatusCode.BadRequest, response.status)
|
||||
}
|
||||
|
||||
// @Test
|
||||
// fun ``() = apiTest { client ->
|
||||
//
|
||||
// }
|
||||
|
||||
// @Test
|
||||
// fun ``() = apiTest { client ->
|
||||
//
|
||||
// }
|
||||
}
|
|
@ -4,18 +4,7 @@ import com.wbrawner.twigs.model.User
|
|||
import com.wbrawner.twigs.storage.UserRepository
|
||||
|
||||
class FakeUserRepository : FakeRepository<User>(), UserRepository {
|
||||
override val entities: MutableList<User> = mutableListOf(
|
||||
User(
|
||||
name = "testuser",
|
||||
email = "test@example.com",
|
||||
password = "\$2a\$10\$bETxbFPja1PyXVLybETxb.CWBYzyYdZpmCcA7NSIN8dkdzidt1Xv2" // testpass
|
||||
),
|
||||
User(
|
||||
name = "otheruser",
|
||||
email = "other@example.com",
|
||||
password = "\$2a\$10\$bETxbFPja1PyXVLybETxb..rhfIeOkP4qil1Drj29LDUhBxVkm6fS"
|
||||
),
|
||||
)
|
||||
override val entities: MutableList<User> = mutableListOf(TEST_USER, OTHER_USER)
|
||||
|
||||
override fun findAll(nameOrEmail: String, password: String?): List<User> {
|
||||
return entities.filter { user ->
|
||||
|
@ -29,4 +18,20 @@ class FakeUserRepository : FakeRepository<User>(), UserRepository {
|
|||
override fun findAll(nameLike: String): List<User> {
|
||||
return entities.filter { it.name.contains(nameLike, ignoreCase = true) }
|
||||
}
|
||||
|
||||
companion object {
|
||||
val TEST_USER = User(
|
||||
id = "id-test-user",
|
||||
name = "testuser",
|
||||
email = "test@example.com",
|
||||
password = "testpass"
|
||||
)
|
||||
|
||||
val OTHER_USER = User(
|
||||
id = "id-other-user",
|
||||
name = "otheruser",
|
||||
email = "other@example.com",
|
||||
password = "otherpass"
|
||||
)
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue