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