mirror of
https://github.com/Dannecron/spring-boot-demo.git
synced 2025-12-25 16:22:35 +03:00
add neko controller
This commit is contained in:
@@ -0,0 +1,26 @@
|
|||||||
|
package com.github.dannecron.demo.http.controllers
|
||||||
|
|
||||||
|
import com.github.dannecron.demo.http.responses.neko.ImagesResponse
|
||||||
|
import com.github.dannecron.demo.services.neko.Client
|
||||||
|
import org.springframework.http.HttpStatus
|
||||||
|
import org.springframework.http.MediaType
|
||||||
|
import org.springframework.http.ResponseEntity
|
||||||
|
import org.springframework.web.bind.annotation.*
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping(value = ["/api/neko"], produces = [MediaType.APPLICATION_JSON_VALUE])
|
||||||
|
class NekoController(
|
||||||
|
private val nekoClient: Client,
|
||||||
|
) {
|
||||||
|
@GetMapping("/categories")
|
||||||
|
fun categories(): ResponseEntity<Any> = ResponseEntity(nekoClient.getCategories(), HttpStatus.OK)
|
||||||
|
|
||||||
|
@GetMapping("/images/{category}")
|
||||||
|
fun images(
|
||||||
|
@PathVariable category: String,
|
||||||
|
@RequestParam imagesCount: Int = 1,
|
||||||
|
): ResponseEntity<Any> = ResponseEntity(
|
||||||
|
ImagesResponse(baseImages = nekoClient.getImages(category = category, amount = imagesCount)),
|
||||||
|
HttpStatus.OK,
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.github.dannecron.demo.http.exceptions
|
package com.github.dannecron.demo.http.exceptions
|
||||||
|
|
||||||
import com.github.dannecron.demo.http.responses.BadRequestResponse
|
import com.github.dannecron.demo.http.responses.BadRequestResponse
|
||||||
|
import com.github.dannecron.demo.http.responses.BaseResponse
|
||||||
import com.github.dannecron.demo.http.responses.NotFoundResponse
|
import com.github.dannecron.demo.http.responses.NotFoundResponse
|
||||||
import com.github.dannecron.demo.http.responses.UnprocessableResponse
|
import com.github.dannecron.demo.http.responses.UnprocessableResponse
|
||||||
import org.springframework.http.HttpStatus
|
import org.springframework.http.HttpStatus
|
||||||
@@ -42,4 +43,12 @@ class ExceptionHandler {
|
|||||||
UnprocessableResponse(exception.javaClass.name, exception.allErrors),
|
UnprocessableResponse(exception.javaClass.name, exception.allErrors),
|
||||||
HttpStatus.UNPROCESSABLE_ENTITY,
|
HttpStatus.UNPROCESSABLE_ENTITY,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// 500
|
||||||
|
@ExceptionHandler(RuntimeException::class)
|
||||||
|
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||||
|
fun handleUnexpectedRuntimeException(exception: RuntimeException): ResponseEntity<Any> = ResponseEntity(
|
||||||
|
BaseResponse(com.github.dannecron.demo.http.responses.ResponseStatus.INTERNAL_ERROR),
|
||||||
|
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,5 +6,6 @@ enum class ResponseStatus(@JsonValue val status: String) {
|
|||||||
OK("ok"),
|
OK("ok"),
|
||||||
NOT_FOUND("not found"),
|
NOT_FOUND("not found"),
|
||||||
BAD_REQUEST("bad request"),
|
BAD_REQUEST("bad request"),
|
||||||
UNPROCESSABLE("unprocessable");
|
UNPROCESSABLE("unprocessable"),
|
||||||
|
INTERNAL_ERROR("internal");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package com.github.dannecron.demo.http.responses.neko
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class Image(
|
||||||
|
val url: String,
|
||||||
|
val animeName: String?,
|
||||||
|
val artistHref: String?,
|
||||||
|
val artistName: String?,
|
||||||
|
val sourceUrl: String?,
|
||||||
|
) {
|
||||||
|
fun isGif() = animeName != null
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package com.github.dannecron.demo.http.responses.neko
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import com.github.dannecron.demo.services.neko.dto.ImagesResponse as BaseResponse
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class ImagesResponse(
|
||||||
|
val images: List<Image>,
|
||||||
|
) {
|
||||||
|
constructor(baseImages: BaseResponse): this(
|
||||||
|
images = baseImages.results.map {
|
||||||
|
Image(it.url, it.animeName, it.artistHref, it.artistName, it.sourceUrl)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
package com.github.dannecron.demo.http.controllers
|
||||||
|
|
||||||
|
import com.github.dannecron.demo.BaseUnitTest
|
||||||
|
import com.github.dannecron.demo.services.neko.Client
|
||||||
|
import com.github.dannecron.demo.services.neko.dto.Image
|
||||||
|
import com.github.dannecron.demo.services.neko.dto.ImagesResponse
|
||||||
|
import org.mockito.kotlin.doReturn
|
||||||
|
import org.mockito.kotlin.whenever
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired
|
||||||
|
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest
|
||||||
|
import org.springframework.boot.test.mock.mockito.MockBean
|
||||||
|
import org.springframework.http.MediaType
|
||||||
|
import org.springframework.test.web.servlet.MockMvc
|
||||||
|
import org.springframework.test.web.servlet.get
|
||||||
|
import kotlin.test.Test
|
||||||
|
|
||||||
|
@WebMvcTest(NekoController::class)
|
||||||
|
class NekoControllerTest(
|
||||||
|
@Autowired val mockMvc: MockMvc,
|
||||||
|
): BaseUnitTest() {
|
||||||
|
@MockBean
|
||||||
|
private lateinit var nekoClient: Client
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun categories_success() {
|
||||||
|
whenever(nekoClient.getCategories()) doReturn setOf("cat1", "cat2")
|
||||||
|
|
||||||
|
mockMvc.get("/api/neko/categories")
|
||||||
|
.andExpect { status { isOk() } }
|
||||||
|
.andExpect { content { contentType(MediaType.APPLICATION_JSON) } }
|
||||||
|
.andExpect { content { string("""["cat1","cat2"]""") } }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun images_success() {
|
||||||
|
val category = "some"
|
||||||
|
val animeName = "boku no pico"
|
||||||
|
whenever(nekoClient.getImages(category = category, amount = 1)) doReturn ImagesResponse(
|
||||||
|
results = listOf(
|
||||||
|
Image(
|
||||||
|
"http://localhost",
|
||||||
|
animeName = animeName,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
mockMvc.get("/api/neko/images/$category")
|
||||||
|
.andExpect { status { isOk() } }
|
||||||
|
.andExpect { content { contentType(MediaType.APPLICATION_JSON) } }
|
||||||
|
.andExpect { jsonPath("\$.images[0].animeName") { value(animeName) } }
|
||||||
|
.andExpect { jsonPath("\$.images[0].artistName") { value(null) } }
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user