mirror of https://github.com/usbharu/Hideout.git
test: Postsのテストを追加
This commit is contained in:
parent
050efb1ee0
commit
22ac04a991
|
@ -0,0 +1,11 @@
|
||||||
|
package dev.usbharu.hideout.domain.model.hideout.dto
|
||||||
|
|
||||||
|
data class UserResponse(
|
||||||
|
val id: Long,
|
||||||
|
val name: String,
|
||||||
|
val domain: String,
|
||||||
|
val screenName: String,
|
||||||
|
val description: String = "",
|
||||||
|
val url: String,
|
||||||
|
val createdAt: Long
|
||||||
|
)
|
|
@ -46,7 +46,7 @@ fun Route.posts(postService: IPostService) {
|
||||||
val minId = call.request.queryParameters["minId"]?.toLong()
|
val minId = call.request.queryParameters["minId"]?.toLong()
|
||||||
val maxId = call.request.queryParameters["maxId"]?.toLong()
|
val maxId = call.request.queryParameters["maxId"]?.toLong()
|
||||||
val limit = call.request.queryParameters["limit"]?.toInt()
|
val limit = call.request.queryParameters["limit"]?.toInt()
|
||||||
call.respond(postService.findAll(since, until, minId, maxId, limit, userId))
|
call.respond(HttpStatusCode.OK, postService.findAll(since, until, minId, maxId, limit, userId))
|
||||||
}
|
}
|
||||||
get("/{id}") {
|
get("/{id}") {
|
||||||
val userId = call.principal<JWTPrincipal>()?.payload?.getClaim("uid")?.asLong()
|
val userId = call.principal<JWTPrincipal>()?.payload?.getClaim("uid")?.asLong()
|
||||||
|
@ -84,7 +84,6 @@ fun Route.posts(postService: IPostService) {
|
||||||
?: throw ParameterNotExistException("Parameter(name='postsId' does not exist.")
|
?: throw ParameterNotExistException("Parameter(name='postsId' does not exist.")
|
||||||
val post = (postService.findByIdForUser(id, userId)
|
val post = (postService.findByIdForUser(id, userId)
|
||||||
?: throw PostNotFoundException("$id was not found or is not authorized."))
|
?: throw PostNotFoundException("$id was not found or is not authorized."))
|
||||||
call.response.header("Content-Location", post.url)
|
|
||||||
call.respond(post)
|
call.respond(post)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ import io.ktor.server.routing.*
|
||||||
fun Route.users(userService: IUserService) {
|
fun Route.users(userService: IUserService) {
|
||||||
route("/users") {
|
route("/users") {
|
||||||
get {
|
get {
|
||||||
call.respond(userService.findAll())
|
call.respond(userService.findAllForUser())
|
||||||
}
|
}
|
||||||
post {
|
post {
|
||||||
val userCreate = call.receive<UserCreate>()
|
val userCreate = call.receive<UserCreate>()
|
||||||
|
@ -34,7 +34,7 @@ fun Route.users(userService: IUserService) {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
call.response.header("Location", "${Config.configData.url}/api/internal/v1/users/${user.name}")
|
call.response.header("Location", "${Config.configData.url}/api/internal/v1/users/${user.name}")
|
||||||
call.respond(HttpStatusCode.OK)
|
call.respond(HttpStatusCode.Created)
|
||||||
}
|
}
|
||||||
route("/{name}") {
|
route("/{name}") {
|
||||||
|
|
||||||
|
|
|
@ -2,12 +2,15 @@ package dev.usbharu.hideout.service.impl
|
||||||
|
|
||||||
import dev.usbharu.hideout.domain.model.hideout.dto.RemoteUserCreateDto
|
import dev.usbharu.hideout.domain.model.hideout.dto.RemoteUserCreateDto
|
||||||
import dev.usbharu.hideout.domain.model.hideout.dto.UserCreateDto
|
import dev.usbharu.hideout.domain.model.hideout.dto.UserCreateDto
|
||||||
|
import dev.usbharu.hideout.domain.model.hideout.dto.UserResponse
|
||||||
import dev.usbharu.hideout.domain.model.hideout.entity.User
|
import dev.usbharu.hideout.domain.model.hideout.entity.User
|
||||||
|
|
||||||
@Suppress("TooManyFunctions")
|
@Suppress("TooManyFunctions")
|
||||||
interface IUserService {
|
interface IUserService {
|
||||||
suspend fun findAll(limit: Int? = 100, offset: Long? = 0): List<User>
|
suspend fun findAll(limit: Int? = 100, offset: Long? = 0): List<User>
|
||||||
|
|
||||||
|
suspend fun findAllForUser(limit: Int? = 100, offset: Long? = 0): List<UserResponse>
|
||||||
|
|
||||||
suspend fun findById(id: Long): User
|
suspend fun findById(id: Long): User
|
||||||
|
|
||||||
suspend fun findByIds(ids: List<Long>): List<User>
|
suspend fun findByIds(ids: List<Long>): List<User>
|
||||||
|
|
|
@ -3,6 +3,7 @@ package dev.usbharu.hideout.service.impl
|
||||||
import dev.usbharu.hideout.config.Config
|
import dev.usbharu.hideout.config.Config
|
||||||
import dev.usbharu.hideout.domain.model.hideout.dto.RemoteUserCreateDto
|
import dev.usbharu.hideout.domain.model.hideout.dto.RemoteUserCreateDto
|
||||||
import dev.usbharu.hideout.domain.model.hideout.dto.UserCreateDto
|
import dev.usbharu.hideout.domain.model.hideout.dto.UserCreateDto
|
||||||
|
import dev.usbharu.hideout.domain.model.hideout.dto.UserResponse
|
||||||
import dev.usbharu.hideout.domain.model.hideout.entity.User
|
import dev.usbharu.hideout.domain.model.hideout.entity.User
|
||||||
import dev.usbharu.hideout.exception.UserNotFoundException
|
import dev.usbharu.hideout.exception.UserNotFoundException
|
||||||
import dev.usbharu.hideout.repository.IUserRepository
|
import dev.usbharu.hideout.repository.IUserRepository
|
||||||
|
@ -23,6 +24,10 @@ class UserService(private val userRepository: IUserRepository, private val userA
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun findAllForUser(limit: Int?, offset: Long?): List<UserResponse> {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
override suspend fun findById(id: Long): User =
|
override suspend fun findById(id: Long): User =
|
||||||
userRepository.findById(id) ?: throw UserNotFoundException("$id was not found.")
|
userRepository.findById(id) ?: throw UserNotFoundException("$id was not found.")
|
||||||
|
|
||||||
|
|
|
@ -1,84 +0,0 @@
|
||||||
package dev.usbharu.hideout.routing.api.internal.v1
|
|
||||||
|
|
||||||
import com.auth0.jwt.interfaces.Claim
|
|
||||||
import com.auth0.jwt.interfaces.Payload
|
|
||||||
import dev.usbharu.hideout.config.Config
|
|
||||||
import dev.usbharu.hideout.domain.model.hideout.dto.PostCreateDto
|
|
||||||
import dev.usbharu.hideout.domain.model.hideout.entity.Visibility
|
|
||||||
import dev.usbharu.hideout.domain.model.hideout.form.Post
|
|
||||||
import dev.usbharu.hideout.plugins.TOKEN_AUTH
|
|
||||||
import dev.usbharu.hideout.plugins.configureSerialization
|
|
||||||
import dev.usbharu.hideout.service.IPostService
|
|
||||||
import io.ktor.client.request.*
|
|
||||||
import io.ktor.http.*
|
|
||||||
import io.ktor.server.auth.*
|
|
||||||
import io.ktor.server.auth.jwt.*
|
|
||||||
import io.ktor.server.config.*
|
|
||||||
import io.ktor.server.routing.*
|
|
||||||
import io.ktor.server.testing.*
|
|
||||||
import org.junit.jupiter.api.Test
|
|
||||||
import org.mockito.kotlin.*
|
|
||||||
import java.time.Instant
|
|
||||||
import kotlin.test.assertEquals
|
|
||||||
|
|
||||||
class PostsKtTest {
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `posts-post postsにpostしたら投稿できる`() = testApplication {
|
|
||||||
environment {
|
|
||||||
config = ApplicationConfig("empty.conf")
|
|
||||||
}
|
|
||||||
val claim = mock<Claim> {
|
|
||||||
on { asLong() } doReturn 1234
|
|
||||||
}
|
|
||||||
val payload = mock<Payload> {
|
|
||||||
on { getClaim(eq("uid")) } doReturn claim
|
|
||||||
}
|
|
||||||
val postService = mock<IPostService> {
|
|
||||||
onBlocking { create(any<PostCreateDto>()) } doAnswer {
|
|
||||||
val argument = it.getArgument<PostCreateDto>(0)
|
|
||||||
dev.usbharu.hideout.domain.model.hideout.entity.Post(
|
|
||||||
123L,
|
|
||||||
argument.userId,
|
|
||||||
null,
|
|
||||||
argument.text,
|
|
||||||
Instant.now().toEpochMilli(),
|
|
||||||
Visibility.PUBLIC,
|
|
||||||
"https://example.com"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
application {
|
|
||||||
authentication {
|
|
||||||
|
|
||||||
bearer(TOKEN_AUTH) {
|
|
||||||
authenticate {
|
|
||||||
println("aaaaaaaaaaaa")
|
|
||||||
JWTPrincipal(payload)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
routing {
|
|
||||||
route("/api/internal/v1") {
|
|
||||||
posts(postService)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
configureSerialization()
|
|
||||||
}
|
|
||||||
|
|
||||||
val post = Post("test")
|
|
||||||
client.post("/api/internal/v1/posts") {
|
|
||||||
header("Authorization", "Bearer asdkaf")
|
|
||||||
contentType(ContentType.Application.Json)
|
|
||||||
setBody(Config.configData.objectMapper.writeValueAsString(post))
|
|
||||||
}.apply {
|
|
||||||
assertEquals(HttpStatusCode.OK, status)
|
|
||||||
assertEquals("https://example.com", headers["Location"])
|
|
||||||
}
|
|
||||||
argumentCaptor<PostCreateDto> {
|
|
||||||
verify(postService).create(capture())
|
|
||||||
assertEquals(PostCreateDto("test", userId = 1234), firstValue)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,619 @@
|
||||||
|
package dev.usbharu.hideout.routing.api.internal.v1
|
||||||
|
|
||||||
|
import com.auth0.jwt.interfaces.Claim
|
||||||
|
import com.auth0.jwt.interfaces.Payload
|
||||||
|
import com.fasterxml.jackson.module.kotlin.readValue
|
||||||
|
import dev.usbharu.hideout.config.Config
|
||||||
|
import dev.usbharu.hideout.domain.model.hideout.dto.PostCreateDto
|
||||||
|
import dev.usbharu.hideout.domain.model.hideout.entity.Post
|
||||||
|
import dev.usbharu.hideout.domain.model.hideout.entity.Visibility
|
||||||
|
import dev.usbharu.hideout.plugins.TOKEN_AUTH
|
||||||
|
import dev.usbharu.hideout.plugins.configureSecurity
|
||||||
|
import dev.usbharu.hideout.plugins.configureSerialization
|
||||||
|
import dev.usbharu.hideout.service.IPostService
|
||||||
|
import io.ktor.client.request.*
|
||||||
|
import io.ktor.client.statement.*
|
||||||
|
import io.ktor.http.*
|
||||||
|
import io.ktor.server.auth.*
|
||||||
|
import io.ktor.server.auth.jwt.*
|
||||||
|
import io.ktor.server.config.*
|
||||||
|
import io.ktor.server.routing.*
|
||||||
|
import io.ktor.server.testing.*
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import org.mockito.kotlin.*
|
||||||
|
import utils.JsonObjectMapper
|
||||||
|
import java.time.Instant
|
||||||
|
import kotlin.test.assertContentEquals
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
class PostsTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun 認証情報無しでpostsにGETしたらPUBLICな投稿一覧が返ってくる() = testApplication {
|
||||||
|
environment {
|
||||||
|
config = ApplicationConfig("empty.conf")
|
||||||
|
}
|
||||||
|
val posts = listOf(
|
||||||
|
Post(
|
||||||
|
id = 12345,
|
||||||
|
userId = 4321,
|
||||||
|
text = "test1",
|
||||||
|
visibility = Visibility.PUBLIC,
|
||||||
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
|
url = "https://example.com/posts/1"
|
||||||
|
),
|
||||||
|
Post(
|
||||||
|
id = 123456,
|
||||||
|
userId = 4322,
|
||||||
|
text = "test2",
|
||||||
|
visibility = Visibility.PUBLIC,
|
||||||
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
|
url = "https://example.com/posts/2"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
val postService = mock<IPostService> {
|
||||||
|
onBlocking {
|
||||||
|
findAll(
|
||||||
|
since = anyOrNull(),
|
||||||
|
until = anyOrNull(),
|
||||||
|
minId = anyOrNull(),
|
||||||
|
maxId = anyOrNull(),
|
||||||
|
limit = anyOrNull(),
|
||||||
|
userId = isNull()
|
||||||
|
)
|
||||||
|
} doReturn posts
|
||||||
|
}
|
||||||
|
application {
|
||||||
|
configureSerialization()
|
||||||
|
configureSecurity(mock(), mock(), mock(), mock(), mock())
|
||||||
|
routing {
|
||||||
|
route("/api/internal/v1") {
|
||||||
|
posts(postService)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
client.get("/api/internal/v1/posts").apply {
|
||||||
|
assertEquals(HttpStatusCode.OK, status)
|
||||||
|
assertContentEquals(posts, JsonObjectMapper.objectMapper.readValue(bodyAsText()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun 認証情報ありでpostsにGETすると権限のある投稿が返ってくる() = testApplication {
|
||||||
|
environment {
|
||||||
|
config = ApplicationConfig("empty.conf")
|
||||||
|
}
|
||||||
|
val claim = mock<Claim> {
|
||||||
|
on { asLong() } doReturn 1234
|
||||||
|
}
|
||||||
|
val payload = mock<Payload> {
|
||||||
|
on { getClaim(eq("uid")) } doReturn claim
|
||||||
|
}
|
||||||
|
|
||||||
|
val posts = listOf(
|
||||||
|
Post(
|
||||||
|
id = 12345,
|
||||||
|
userId = 4321,
|
||||||
|
text = "test1",
|
||||||
|
visibility = Visibility.PUBLIC,
|
||||||
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
|
url = "https://example.com/posts/1"
|
||||||
|
),
|
||||||
|
Post(
|
||||||
|
id = 123456,
|
||||||
|
userId = 4322,
|
||||||
|
text = "test2",
|
||||||
|
visibility = Visibility.PUBLIC,
|
||||||
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
|
url = "https://example.com/posts/2"
|
||||||
|
),
|
||||||
|
Post(
|
||||||
|
id = 1234567,
|
||||||
|
userId = 4333,
|
||||||
|
text = "Followers only",
|
||||||
|
visibility = Visibility.FOLLOWERS,
|
||||||
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
|
url = "https://example.com/posts/3"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
val postService = mock<IPostService> {
|
||||||
|
onBlocking {
|
||||||
|
findAll(
|
||||||
|
since = anyOrNull(),
|
||||||
|
until = anyOrNull(),
|
||||||
|
minId = anyOrNull(),
|
||||||
|
maxId = anyOrNull(),
|
||||||
|
limit = anyOrNull(),
|
||||||
|
userId = isNotNull()
|
||||||
|
)
|
||||||
|
} doReturn posts
|
||||||
|
}
|
||||||
|
application {
|
||||||
|
authentication {
|
||||||
|
bearer(TOKEN_AUTH) {
|
||||||
|
authenticate {
|
||||||
|
JWTPrincipal(payload)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
configureSerialization()
|
||||||
|
routing {
|
||||||
|
route("/api/internal/v1") {
|
||||||
|
posts(postService)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
client.get("/api/internal/v1/posts") {
|
||||||
|
header("Authorization", "Bearer asdkaf")
|
||||||
|
}.apply {
|
||||||
|
assertEquals(HttpStatusCode.OK, status)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `posts id にGETしたらPUBLICな投稿を取得できる`() = testApplication {
|
||||||
|
environment {
|
||||||
|
config = ApplicationConfig("empty.conf")
|
||||||
|
}
|
||||||
|
val post = Post(
|
||||||
|
12345, 1234, text = "aaa", visibility = Visibility.PUBLIC,
|
||||||
|
createdAt = Instant.now().toEpochMilli(), url = "https://example.com/posts/1"
|
||||||
|
)
|
||||||
|
val postService = mock<IPostService> {
|
||||||
|
onBlocking { findByIdForUser(any(), anyOrNull()) } doReturn post
|
||||||
|
}
|
||||||
|
application {
|
||||||
|
configureSerialization()
|
||||||
|
configureSecurity(mock(), mock(), mock(), mock(), mock())
|
||||||
|
routing {
|
||||||
|
route("/api/internal/v1") {
|
||||||
|
posts(postService)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
client.get("/api/internal/v1/posts/1").apply {
|
||||||
|
assertEquals(HttpStatusCode.OK, status)
|
||||||
|
assertEquals(post, JsonObjectMapper.objectMapper.readValue(bodyAsText()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `認証情報ありでposts id にGETしたら権限のある投稿を取得できる`() = testApplication {
|
||||||
|
environment {
|
||||||
|
config = ApplicationConfig("empty.conf")
|
||||||
|
}
|
||||||
|
val post = Post(
|
||||||
|
12345, 1234, text = "aaa", visibility = Visibility.FOLLOWERS,
|
||||||
|
createdAt = Instant.now().toEpochMilli(), url = "https://example.com/posts/1"
|
||||||
|
)
|
||||||
|
val postService = mock<IPostService> {
|
||||||
|
onBlocking { findByIdForUser(any(), isNotNull()) } doReturn post
|
||||||
|
}
|
||||||
|
val claim = mock<Claim> {
|
||||||
|
on { asLong() } doReturn 1234
|
||||||
|
}
|
||||||
|
val payload = mock<Payload> {
|
||||||
|
on { getClaim(eq("uid")) } doReturn claim
|
||||||
|
}
|
||||||
|
application {
|
||||||
|
configureSerialization()
|
||||||
|
authentication {
|
||||||
|
bearer(TOKEN_AUTH) {
|
||||||
|
authenticate {
|
||||||
|
JWTPrincipal(payload)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
routing {
|
||||||
|
route("/api/internal/v1") {
|
||||||
|
posts(postService)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
client.get("/api/internal/v1/posts/1") {
|
||||||
|
header("Authorization", "Bearer asdkaf")
|
||||||
|
}.apply {
|
||||||
|
assertEquals(HttpStatusCode.OK, status)
|
||||||
|
assertEquals(post, JsonObjectMapper.objectMapper.readValue(bodyAsText()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `posts-post postsにpostしたら投稿できる`() = testApplication {
|
||||||
|
environment {
|
||||||
|
config = ApplicationConfig("empty.conf")
|
||||||
|
}
|
||||||
|
val claim = mock<Claim> {
|
||||||
|
on { asLong() } doReturn 1234
|
||||||
|
}
|
||||||
|
val payload = mock<Payload> {
|
||||||
|
on { getClaim(eq("uid")) } doReturn claim
|
||||||
|
}
|
||||||
|
val postService = mock<IPostService> {
|
||||||
|
onBlocking { create(any<PostCreateDto>()) } doAnswer {
|
||||||
|
val argument = it.getArgument<PostCreateDto>(0)
|
||||||
|
Post(
|
||||||
|
123L,
|
||||||
|
argument.userId,
|
||||||
|
null,
|
||||||
|
argument.text,
|
||||||
|
Instant.now().toEpochMilli(),
|
||||||
|
Visibility.PUBLIC,
|
||||||
|
"https://example.com"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
application {
|
||||||
|
authentication {
|
||||||
|
|
||||||
|
bearer(TOKEN_AUTH) {
|
||||||
|
authenticate {
|
||||||
|
println("aaaaaaaaaaaa")
|
||||||
|
JWTPrincipal(payload)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
routing {
|
||||||
|
route("/api/internal/v1") {
|
||||||
|
posts(postService)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
configureSerialization()
|
||||||
|
}
|
||||||
|
|
||||||
|
val post = dev.usbharu.hideout.domain.model.hideout.form.Post("test")
|
||||||
|
client.post("/api/internal/v1/posts") {
|
||||||
|
header("Authorization", "Bearer asdkaf")
|
||||||
|
contentType(ContentType.Application.Json)
|
||||||
|
setBody(Config.configData.objectMapper.writeValueAsString(post))
|
||||||
|
}.apply {
|
||||||
|
assertEquals(HttpStatusCode.OK, status)
|
||||||
|
assertEquals("https://example.com", headers["Location"])
|
||||||
|
}
|
||||||
|
argumentCaptor<PostCreateDto> {
|
||||||
|
verify(postService).create(capture())
|
||||||
|
assertEquals(PostCreateDto("test", userId = 1234), firstValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `users userId postsにGETしたらユーザーのPUBLICな投稿一覧を取得できる`() = testApplication {
|
||||||
|
environment {
|
||||||
|
config = ApplicationConfig("empty.conf")
|
||||||
|
}
|
||||||
|
val posts = listOf(
|
||||||
|
Post(
|
||||||
|
id = 12345,
|
||||||
|
userId = 1,
|
||||||
|
text = "test1",
|
||||||
|
visibility = Visibility.PUBLIC,
|
||||||
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
|
url = "https://example.com/posts/1"
|
||||||
|
),
|
||||||
|
Post(
|
||||||
|
id = 123456,
|
||||||
|
userId = 1,
|
||||||
|
text = "test2",
|
||||||
|
visibility = Visibility.PUBLIC,
|
||||||
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
|
url = "https://example.com/posts/2"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
val postService = mock<IPostService> {
|
||||||
|
onBlocking {
|
||||||
|
findByUserIdForUser(
|
||||||
|
userId = any(),
|
||||||
|
since = anyOrNull(),
|
||||||
|
until = anyOrNull(),
|
||||||
|
minId = anyOrNull(),
|
||||||
|
maxId = anyOrNull(),
|
||||||
|
limit = anyOrNull(),
|
||||||
|
forUserId = anyOrNull()
|
||||||
|
)
|
||||||
|
} doReturn posts
|
||||||
|
}
|
||||||
|
application {
|
||||||
|
configureSerialization()
|
||||||
|
configureSecurity(mock(), mock(), mock(), mock(), mock())
|
||||||
|
routing {
|
||||||
|
route("/api/internal/v1") {
|
||||||
|
posts(postService)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
client.get("/api/internal/v1/users/1/posts").apply {
|
||||||
|
assertEquals(HttpStatusCode.OK, status)
|
||||||
|
assertEquals(posts, JsonObjectMapper.objectMapper.readValue(bodyAsText()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `users username postsにGETしたらユーザーのPUBLICな投稿一覧を取得できる`() = testApplication {
|
||||||
|
environment {
|
||||||
|
config = ApplicationConfig("empty.conf")
|
||||||
|
}
|
||||||
|
val posts = listOf(
|
||||||
|
Post(
|
||||||
|
id = 12345,
|
||||||
|
userId = 1,
|
||||||
|
text = "test1",
|
||||||
|
visibility = Visibility.PUBLIC,
|
||||||
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
|
url = "https://example.com/posts/1"
|
||||||
|
),
|
||||||
|
Post(
|
||||||
|
id = 123456,
|
||||||
|
userId = 1,
|
||||||
|
text = "test2",
|
||||||
|
visibility = Visibility.PUBLIC,
|
||||||
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
|
url = "https://example.com/posts/2"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
val postService = mock<IPostService> {
|
||||||
|
onBlocking {
|
||||||
|
findByUserNameAndDomainForUser(
|
||||||
|
userName = eq("test1"),
|
||||||
|
domain = eq(Config.configData.domain),
|
||||||
|
since = anyOrNull(),
|
||||||
|
until = anyOrNull(),
|
||||||
|
minId = anyOrNull(),
|
||||||
|
maxId = anyOrNull(),
|
||||||
|
limit = anyOrNull(),
|
||||||
|
forUserId = anyOrNull()
|
||||||
|
)
|
||||||
|
} doReturn posts
|
||||||
|
}
|
||||||
|
application {
|
||||||
|
configureSerialization()
|
||||||
|
configureSecurity(mock(), mock(), mock(), mock(), mock())
|
||||||
|
routing {
|
||||||
|
route("/api/internal/v1") {
|
||||||
|
posts(postService)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
client.get("/api/internal/v1/users/test1/posts").apply {
|
||||||
|
assertEquals(HttpStatusCode.OK, status)
|
||||||
|
assertEquals(posts, JsonObjectMapper.objectMapper.readValue(bodyAsText()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `users username@domain postsにGETしたらユーザーのPUBLICな投稿一覧を取得できる`() = testApplication {
|
||||||
|
environment {
|
||||||
|
config = ApplicationConfig("empty.conf")
|
||||||
|
}
|
||||||
|
val posts = listOf(
|
||||||
|
Post(
|
||||||
|
id = 12345,
|
||||||
|
userId = 1,
|
||||||
|
text = "test1",
|
||||||
|
visibility = Visibility.PUBLIC,
|
||||||
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
|
url = "https://example.com/posts/1"
|
||||||
|
),
|
||||||
|
Post(
|
||||||
|
id = 123456,
|
||||||
|
userId = 1,
|
||||||
|
text = "test2",
|
||||||
|
visibility = Visibility.PUBLIC,
|
||||||
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
|
url = "https://example.com/posts/2"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
val postService = mock<IPostService> {
|
||||||
|
onBlocking {
|
||||||
|
findByUserNameAndDomainForUser(
|
||||||
|
userName = eq("test1"),
|
||||||
|
domain = eq("example.com"),
|
||||||
|
since = anyOrNull(),
|
||||||
|
until = anyOrNull(),
|
||||||
|
minId = anyOrNull(),
|
||||||
|
maxId = anyOrNull(),
|
||||||
|
limit = anyOrNull(),
|
||||||
|
forUserId = anyOrNull()
|
||||||
|
)
|
||||||
|
} doReturn posts
|
||||||
|
}
|
||||||
|
application {
|
||||||
|
configureSerialization()
|
||||||
|
configureSecurity(mock(), mock(), mock(), mock(), mock())
|
||||||
|
routing {
|
||||||
|
route("/api/internal/v1") {
|
||||||
|
posts(postService)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
client.get("/api/internal/v1/users/test1@example.com/posts").apply {
|
||||||
|
assertEquals(HttpStatusCode.OK, status)
|
||||||
|
assertEquals(posts, JsonObjectMapper.objectMapper.readValue(bodyAsText()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `users @username@domain postsにGETしたらユーザーのPUBLICな投稿一覧を取得できる`() = testApplication {
|
||||||
|
environment {
|
||||||
|
config = ApplicationConfig("empty.conf")
|
||||||
|
}
|
||||||
|
val posts = listOf(
|
||||||
|
Post(
|
||||||
|
id = 12345,
|
||||||
|
userId = 1,
|
||||||
|
text = "test1",
|
||||||
|
visibility = Visibility.PUBLIC,
|
||||||
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
|
url = "https://example.com/posts/1"
|
||||||
|
),
|
||||||
|
Post(
|
||||||
|
id = 123456,
|
||||||
|
userId = 1,
|
||||||
|
text = "test2",
|
||||||
|
visibility = Visibility.PUBLIC,
|
||||||
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
|
url = "https://example.com/posts/2"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
val postService = mock<IPostService> {
|
||||||
|
onBlocking {
|
||||||
|
findByUserNameAndDomainForUser(
|
||||||
|
userName = eq("test1"),
|
||||||
|
domain = eq("example.com"),
|
||||||
|
since = anyOrNull(),
|
||||||
|
until = anyOrNull(),
|
||||||
|
minId = anyOrNull(),
|
||||||
|
maxId = anyOrNull(),
|
||||||
|
limit = anyOrNull(),
|
||||||
|
forUserId = anyOrNull()
|
||||||
|
)
|
||||||
|
} doReturn posts
|
||||||
|
}
|
||||||
|
application {
|
||||||
|
configureSerialization()
|
||||||
|
configureSecurity(mock(), mock(), mock(), mock(), mock())
|
||||||
|
routing {
|
||||||
|
route("/api/internal/v1") {
|
||||||
|
posts(postService)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
client.get("/api/internal/v1/users/@test1@example.com/posts").apply {
|
||||||
|
assertEquals(HttpStatusCode.OK, status)
|
||||||
|
assertEquals(posts, JsonObjectMapper.objectMapper.readValue(bodyAsText()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `users name posts id にGETしたらPUBLICな投稿を取得できる`() = testApplication {
|
||||||
|
environment {
|
||||||
|
config = ApplicationConfig("empty.conf")
|
||||||
|
}
|
||||||
|
val post = Post(
|
||||||
|
id = 123456,
|
||||||
|
userId = 1,
|
||||||
|
text = "test2",
|
||||||
|
visibility = Visibility.PUBLIC,
|
||||||
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
|
url = "https://example.com/posts/2"
|
||||||
|
)
|
||||||
|
val postService = mock<IPostService> {
|
||||||
|
onBlocking { findByIdForUser(eq(12345L), anyOrNull()) } doReturn post
|
||||||
|
}
|
||||||
|
application {
|
||||||
|
configureSerialization()
|
||||||
|
configureSecurity(mock(), mock(), mock(), mock(), mock())
|
||||||
|
routing {
|
||||||
|
route("/api/internal/v1") {
|
||||||
|
posts(postService)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
client.get("/api/internal/v1/users/test/posts/12345").apply {
|
||||||
|
assertEquals(HttpStatusCode.OK, status)
|
||||||
|
assertEquals(post, JsonObjectMapper.objectMapper.readValue(bodyAsText()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `users id posts id にGETしたらPUBLICな投稿を取得できる`() = testApplication {
|
||||||
|
environment {
|
||||||
|
config = ApplicationConfig("empty.conf")
|
||||||
|
}
|
||||||
|
val post = Post(
|
||||||
|
id = 123456,
|
||||||
|
userId = 1,
|
||||||
|
text = "test2",
|
||||||
|
visibility = Visibility.PUBLIC,
|
||||||
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
|
url = "https://example.com/posts/2"
|
||||||
|
)
|
||||||
|
val postService = mock<IPostService> {
|
||||||
|
onBlocking { findByIdForUser(eq(12345L), anyOrNull()) } doReturn post
|
||||||
|
}
|
||||||
|
application {
|
||||||
|
configureSerialization()
|
||||||
|
configureSecurity(mock(), mock(), mock(), mock(), mock())
|
||||||
|
routing {
|
||||||
|
route("/api/internal/v1") {
|
||||||
|
posts(postService)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
client.get("/api/internal/v1/users/1/posts/12345").apply {
|
||||||
|
assertEquals(HttpStatusCode.OK, status)
|
||||||
|
assertEquals(post, JsonObjectMapper.objectMapper.readValue(bodyAsText()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `users name posts id にGETしたらUserIdが間違っててもPUBLICな投稿を取得できる`() = testApplication {
|
||||||
|
environment {
|
||||||
|
config = ApplicationConfig("empty.conf")
|
||||||
|
}
|
||||||
|
val post = Post(
|
||||||
|
id = 123456,
|
||||||
|
userId = 1,
|
||||||
|
text = "test2",
|
||||||
|
visibility = Visibility.PUBLIC,
|
||||||
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
|
url = "https://example.com/posts/2"
|
||||||
|
)
|
||||||
|
val postService = mock<IPostService> {
|
||||||
|
onBlocking { findByIdForUser(eq(12345L), anyOrNull()) } doReturn post
|
||||||
|
}
|
||||||
|
application {
|
||||||
|
configureSerialization()
|
||||||
|
configureSecurity(mock(), mock(), mock(), mock(), mock())
|
||||||
|
routing {
|
||||||
|
route("/api/internal/v1") {
|
||||||
|
posts(postService)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
client.get("/api/internal/v1/users/423827849732847/posts/12345").apply {
|
||||||
|
assertEquals(HttpStatusCode.OK, status)
|
||||||
|
assertEquals(post, JsonObjectMapper.objectMapper.readValue(bodyAsText()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `users name posts id にGETしたらuserNameが間違っててもPUBLICな投稿を取得できる`() = testApplication {
|
||||||
|
environment {
|
||||||
|
config = ApplicationConfig("empty.conf")
|
||||||
|
}
|
||||||
|
val post = Post(
|
||||||
|
id = 123456,
|
||||||
|
userId = 1,
|
||||||
|
text = "test2",
|
||||||
|
visibility = Visibility.PUBLIC,
|
||||||
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
|
url = "https://example.com/posts/2"
|
||||||
|
)
|
||||||
|
val postService = mock<IPostService> {
|
||||||
|
onBlocking { findByIdForUser(eq(12345L), anyOrNull()) } doReturn post
|
||||||
|
}
|
||||||
|
application {
|
||||||
|
configureSerialization()
|
||||||
|
configureSecurity(mock(), mock(), mock(), mock(), mock())
|
||||||
|
routing {
|
||||||
|
route("/api/internal/v1") {
|
||||||
|
posts(postService)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
client.get("/api/internal/v1/users/invalidUserName/posts/12345").apply {
|
||||||
|
assertEquals(HttpStatusCode.OK, status)
|
||||||
|
assertEquals(post, JsonObjectMapper.objectMapper.readValue(bodyAsText()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,142 @@
|
||||||
|
package dev.usbharu.hideout.routing.api.internal.v1
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.module.kotlin.readValue
|
||||||
|
import dev.usbharu.hideout.config.Config
|
||||||
|
import dev.usbharu.hideout.domain.model.hideout.dto.UserResponse
|
||||||
|
import dev.usbharu.hideout.domain.model.hideout.entity.User
|
||||||
|
import dev.usbharu.hideout.domain.model.hideout.form.UserCreate
|
||||||
|
import dev.usbharu.hideout.plugins.configureSecurity
|
||||||
|
import dev.usbharu.hideout.plugins.configureSerialization
|
||||||
|
import dev.usbharu.hideout.service.impl.IUserService
|
||||||
|
import io.ktor.client.request.*
|
||||||
|
import io.ktor.client.statement.*
|
||||||
|
import io.ktor.http.*
|
||||||
|
import io.ktor.server.config.*
|
||||||
|
import io.ktor.server.routing.*
|
||||||
|
import io.ktor.server.testing.*
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import org.mockito.kotlin.any
|
||||||
|
import org.mockito.kotlin.anyOrNull
|
||||||
|
import org.mockito.kotlin.doReturn
|
||||||
|
import org.mockito.kotlin.mock
|
||||||
|
import utils.JsonObjectMapper
|
||||||
|
import java.time.Instant
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
class UsersTest {
|
||||||
|
@Test
|
||||||
|
fun `users にGETするとユーザー一覧を取得できる`() = testApplication {
|
||||||
|
environment {
|
||||||
|
config = ApplicationConfig("empty.conf")
|
||||||
|
}
|
||||||
|
|
||||||
|
val users = listOf(
|
||||||
|
UserResponse(
|
||||||
|
12345,
|
||||||
|
"test1",
|
||||||
|
"example.com",
|
||||||
|
"test",
|
||||||
|
"",
|
||||||
|
"https://example.com/test",
|
||||||
|
Instant.now().toEpochMilli()
|
||||||
|
),
|
||||||
|
UserResponse(
|
||||||
|
12343,
|
||||||
|
"tes2",
|
||||||
|
"example.com",
|
||||||
|
"test",
|
||||||
|
"",
|
||||||
|
"https://example.com/tes2",
|
||||||
|
Instant.now().toEpochMilli()
|
||||||
|
),
|
||||||
|
)
|
||||||
|
val userService = mock<IUserService> {
|
||||||
|
onBlocking { findAllForUser(anyOrNull(), anyOrNull()) } doReturn users
|
||||||
|
}
|
||||||
|
application {
|
||||||
|
configureSerialization()
|
||||||
|
configureSecurity(mock(), mock(), mock(), mock(), mock())
|
||||||
|
routing {
|
||||||
|
route("/api/internal/v1") {
|
||||||
|
users(userService)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
client.get("/api/internal/v1/users").apply {
|
||||||
|
assertEquals(HttpStatusCode.OK, status)
|
||||||
|
assertEquals(users, JsonObjectMapper.objectMapper.readValue(bodyAsText()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `users にPOSTすると新規ユーザー作成ができる`() = testApplication {
|
||||||
|
environment {
|
||||||
|
config = ApplicationConfig("empty.conf")
|
||||||
|
}
|
||||||
|
val userCreateDto = UserCreate("test", "XXXXXXX")
|
||||||
|
val userService = mock<IUserService> {
|
||||||
|
onBlocking { usernameAlreadyUse(any()) } doReturn false
|
||||||
|
onBlocking { createLocalUser(any()) } doReturn User(
|
||||||
|
id = 12345,
|
||||||
|
name = "test",
|
||||||
|
domain = "example.com",
|
||||||
|
screenName = "testUser",
|
||||||
|
description = "test user",
|
||||||
|
password = "XXXXXXX",
|
||||||
|
inbox = "https://example.com/inbox",
|
||||||
|
outbox = "https://example.com/outbox",
|
||||||
|
url = "https://example.com",
|
||||||
|
publicKey = "-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----",
|
||||||
|
privateKey = "-----BEGIN PRIVATE KEY-----...-----END PRIVATE KEY-----",
|
||||||
|
createdAt = Instant.now()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
application {
|
||||||
|
configureSerialization()
|
||||||
|
configureSecurity(mock(), mock(), mock(), mock(), mock())
|
||||||
|
routing {
|
||||||
|
route("/api/internal/v1") {
|
||||||
|
users(userService)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
client.post("/api/internal/v1/users") {
|
||||||
|
contentType(ContentType.Application.Json)
|
||||||
|
setBody(JsonObjectMapper.objectMapper.writeValueAsString(userCreateDto))
|
||||||
|
}.apply {
|
||||||
|
assertEquals(HttpStatusCode.Created, status)
|
||||||
|
assertEquals(
|
||||||
|
"${Config.configData.url}/api/internal/v1/users/${userCreateDto.username}",
|
||||||
|
headers["Location"]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `users 既にユーザー名が使用されているときはBadRequestが帰ってくる`() = testApplication {
|
||||||
|
environment {
|
||||||
|
config = ApplicationConfig("empty.conf")
|
||||||
|
}
|
||||||
|
val userCreateDto = UserCreate("test", "XXXXXXX")
|
||||||
|
val userService = mock<IUserService> {
|
||||||
|
onBlocking { usernameAlreadyUse(any()) } doReturn true
|
||||||
|
}
|
||||||
|
application {
|
||||||
|
configureSerialization()
|
||||||
|
configureSecurity(mock(), mock(), mock(), mock(), mock())
|
||||||
|
routing {
|
||||||
|
route("/api/internal/v1") {
|
||||||
|
users(userService)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
client.post("/api/internal/v1/users") {
|
||||||
|
contentType(ContentType.Application.Json)
|
||||||
|
setBody(JsonObjectMapper.objectMapper.writeValueAsString(userCreateDto))
|
||||||
|
}.apply {
|
||||||
|
assertEquals(HttpStatusCode.BadRequest, status)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue