Skip to content
This repository has been archived by the owner on May 25, 2020. It is now read-only.

Commit

Permalink
progress on comments
Browse files Browse the repository at this point in the history
  • Loading branch information
AndreasVolkmann committed Aug 12, 2018
1 parent 95aaccb commit 36ce637
Show file tree
Hide file tree
Showing 9 changed files with 97 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ data class Comment(
val author: Profile
)

data class NewComment(val body: String)
data class NewComment(val comment: Body) {
val body get() = comment.body
}

class Body(val body: String)

class CommentsWrapper(val comments: List<Comment>)
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ interface ArticleRepository {

fun getArticle(slug: String): ArticleDetails

fun insertArticle(user: User, article: Article)
fun insertArticle(user: User, article: Article): ArticleDetails

fun updateArticle(articleDetails: ArticleDetails): ArticleDetails?

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class ArticleRepositoryImpl : ArticleRepository {

}

override fun insertArticle(user: User, article: Article) = transaction {
override fun insertArticle(user: User, article: Article): ArticleDetails = transaction {
val id = Articles.insert {
it[slug] = article.slug
it[title] = article.title
Expand All @@ -51,9 +51,22 @@ class ArticleRepositoryImpl : ArticleRepository {
it[createdAt] = article.createdAt
it[updatedAt] = article.updatedAt
it[authorId] = user.id
} get Articles.id ?: TODO()
} get Articles.id ?: throw Exception("") // TODO improve exception

insertTags(id, article.tagList)
ArticleDetails(
id,
article.slug,
article.title,
article.description,
article.body,
article.tagList,
article.createdAt,
article.updatedAt,
false, // TODO
0, // TODO
user.profile
)
}

fun insertTags(articleId: Int, tags: List<String>) = transaction {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import me.avo.realworld.kotlin.ktor.model.User

interface CommentRepository {

fun addComment(comment: NewComment, slug: String): Comment
fun addComment(user: User, comment: NewComment, slug: String): Comment

fun getComments(slug: String, user: User?): List<Comment>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,35 @@
package me.avo.realworld.kotlin.ktor.repository

import io.ktor.http.HttpStatusCode
import me.avo.realworld.kotlin.ktor.model.Comment
import me.avo.realworld.kotlin.ktor.model.NewComment
import me.avo.realworld.kotlin.ktor.model.Profile
import me.avo.realworld.kotlin.ktor.model.User
import org.jetbrains.exposed.sql.Join
import org.jetbrains.exposed.sql.JoinType
import org.jetbrains.exposed.sql.select
import me.avo.realworld.kotlin.ktor.server.StatusException
import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.transactions.transaction
import org.joda.time.DateTime

class CommentRepositoryImpl : CommentRepository {

override fun addComment(comment: NewComment, slug: String): Comment {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
private class ArticleNotFoundException(slug: String) :
StatusException("Could not find Article with slug $slug", HttpStatusCode.NotFound)

override fun addComment(user: User, comment: NewComment, slug: String): Comment = transaction {
val articleId = Articles
.slice(Articles.id)
.select { Articles.slug eq slug }
.firstOrNull()
?.get(Articles.id) ?: throw ArticleNotFoundException(slug)
val date = DateTime()
val id = Comments.insert {
it[body] = comment.body
it[article_id] = articleId
it[createdAt] = date
it[updatedAt] = date
it[authorId] = user.id
} get Comments.id ?: throw Exception() // TODO improve exception
Comment(id, date, date, comment.body, user.profile)
}

override fun getComments(slug: String, user: User?): List<Comment> = transaction {
Expand All @@ -39,8 +56,8 @@ class CommentRepositoryImpl : CommentRepository {
}
}

override fun deleteComment(slug: String, id: String) {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
override fun deleteComment(slug: String, id: String): Unit = transaction {
Comments.deleteWhere { Comments.id eq id.toInt() }
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ object Favorites : Table("favorites") {
}

object Comments : Table("comments") {
val id = integer("id").primaryKey().autoIncrement()
val article_id = integer("article_id") references Articles.id
val id = integer("id").primaryKey()
val createdAt = datetime("createdAt")
val updatedAt = datetime("updatedAt")
val body = text("body")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ fun Route.article(articleRepository: ArticleRepository) = route("articles") {
post {
val newComment = call.receive<NewComment>()
val slug = call.getSlug()
val comment = commentRepository.addComment(newComment, slug)
val comment = commentRepository.addComment(call.user!!, newComment, slug)
call.respond(comment)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,58 +3,82 @@ package me.avo.realworld.kotlin.ktor.functional
import com.github.salomonbrys.kotson.array
import com.github.salomonbrys.kotson.obj
import com.github.salomonbrys.kotson.string
import com.google.gson.JsonArray
import com.google.gson.JsonObject
import io.ktor.http.HttpMethod
import me.avo.realworld.kotlin.ktor.model.Article
import me.avo.realworld.kotlin.ktor.model.Body
import me.avo.realworld.kotlin.ktor.model.NewComment
import me.avo.realworld.kotlin.ktor.model.RegistrationDetails
import me.avo.realworld.kotlin.ktor.repository.ArticleRepositoryImpl
import me.avo.realworld.kotlin.ktor.repository.CommentRepositoryImpl
import org.amshove.kluent.shouldBeEqualTo
import org.amshove.kluent.shouldBeGreaterOrEqualTo
import org.joda.time.DateTime
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.TestInstance
import java.time.OffsetDateTime

@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class CommentsTest : FunctionalTest {

override val rootUri = "articles/how-to-train-your-dragon/comments"
private val slug = "how-to-train-your-dragon"
override val rootUri = "articles/$slug/comments"
private val commentRepository = CommentRepositoryImpl()
private val articleRepository = ArticleRepositoryImpl()
private val user = ensureUserExists(RegistrationDetails("comment", "co@mmen.ts", "test"))
private val article = articleRepository.insertArticle(
user, Article("How to train your dragon", "x", "y", listOf("new"), slug, DateTime(), DateTime())
)
private val commentToDelete by lazy { commentRepository.addComment(user, NewComment(Body("test")), article.slug) }

init {
commentRepository.addComment(user, NewComment(Body("test")), article.slug)
}

@Test fun `All Comments for Article`() = handleRequest(tokenUser = ensureUserExists()) {
commentCheck(it)
}

@Test fun `Create Comment for Article`() = handleRequest(
method = HttpMethod.Post,
tokenUser = ensureUserExists(),
body = "{\"comment\":{\"body\":\"Thank you so much!\"}}"
) {
commentCheck(it)
@Test fun `Create Comment for Article`() {
val body = "Thank you so much!"
handleRequest(
method = HttpMethod.Post,
tokenUser = ensureUserExists(),
body = "{\"comment\":{\"body\":\"$body\"}}"
) {
commentBodyCheck(it)
it["body"].string shouldBeEqualTo body
}
}

@Test fun `Delete Comment for Article`() {
val comment = CommentRepositoryImpl().addComment(NewComment("test"), "x")
handleRequest(
uri = "$rootUri/${comment.id}",
uri = "$rootUri/${commentToDelete.id}",
method = HttpMethod.Delete,
tokenUser = ensureUserExists()
) {

}
}

private fun commentCheck(json: JsonObject) = json shouldHaveOwnProperty "comments" and {
val comments = it.array
comments.size() shouldBeGreaterOrEqualTo 1
comments.first().obj.let {
it shouldHaveOwnProperty "id"
it shouldHaveOwnProperty "body"
it shouldHaveOwnProperty "createdAt" and {
OffsetDateTime.parse(it.string).toString() shouldBeEqualTo it.string
}
it shouldHaveOwnProperty "updatedAt" and {
OffsetDateTime.parse(it.string).toString() shouldBeEqualTo it.string
}
it shouldHaveOwnProperty "author"
private fun commentCheck(json: JsonObject): JsonArray = json shouldHaveOwnProperty "comments" and {
it.array.apply {
size() shouldBeGreaterOrEqualTo 1
first().obj.let(::commentBodyCheck)
}
}

private fun commentBodyCheck(json: JsonObject) {
json shouldHaveOwnProperty "id"
json shouldHaveOwnProperty "body"
json shouldHaveOwnProperty "createdAt" and {
OffsetDateTime.parse(json.string).toString() shouldBeEqualTo it.string
}
json shouldHaveOwnProperty "updatedAt" and {
OffsetDateTime.parse(it.string).toString() shouldBeEqualTo it.string
}
json shouldHaveOwnProperty "author"
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,6 @@ infix fun JsonObject.shouldHaveOwnProperty(name: String): JsonElement {
return this[name]
}

infix fun JsonElement.and(block: (JsonElement) -> Unit) {
block(this)
infix fun <T> JsonElement.and(block: (JsonElement) -> T): T {
return block(this)
}

0 comments on commit 36ce637

Please sign in to comment.