Add validation on route CreateComments & EditComment
rename POST /comments/{comment}/children
method edit and create comment of repository return edited/created comment
This commit is contained in:
@@ -63,12 +63,14 @@ open class CommentForUpdate<T : TargetI, C : CitizenI>(
|
|||||||
constructor(
|
constructor(
|
||||||
createdBy: C,
|
createdBy: C,
|
||||||
parent: CommentParent<T>,
|
parent: CommentParent<T>,
|
||||||
content: String
|
content: String,
|
||||||
|
id: UUID? = null,
|
||||||
) : this(
|
) : this(
|
||||||
createdBy = createdBy,
|
createdBy = createdBy,
|
||||||
parent = parent,
|
parent = parent,
|
||||||
target = parent.target,
|
target = parent.target,
|
||||||
content = content
|
content = content,
|
||||||
|
id = id ?: UUID.randomUUID(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -58,35 +58,29 @@ abstract class CommentRepositoryAbs<T : TargetI>(override var requester: Request
|
|||||||
page: Int = 1,
|
page: Int = 1,
|
||||||
limit: Int = 50,
|
limit: Int = 50,
|
||||||
sort: String = "createdAt"
|
sort: String = "createdAt"
|
||||||
): Paginated<CommentForView<T, CitizenCreatorI>> {
|
): Paginated<CommentForView<T, CitizenCreatorI>> = requester
|
||||||
return requester.run {
|
.getFunction("find_comments_by_target")
|
||||||
getFunction("find_comments_by_target")
|
|
||||||
.select<CommentForView<T, CitizenCreator>>(
|
.select<CommentForView<T, CitizenCreator>>(
|
||||||
page,
|
page,
|
||||||
limit,
|
limit,
|
||||||
"target_id" to targetId,
|
"target_id" to targetId,
|
||||||
"sort" to sort
|
"sort" to sort
|
||||||
)
|
) as Paginated<CommentForView<T, CitizenCreatorI>>
|
||||||
as Paginated<CommentForView<T, CitizenCreatorI>>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <I : TargetI, C : CitizenCreatorI> comment(comment: CommentForUpdate<I, C>) {
|
fun <I : TargetI, C : CitizenCreatorI> comment(comment: CommentForUpdate<I, C>): CommentForView<TargetRef, CitizenCreator> = requester
|
||||||
requester
|
|
||||||
.getFunction("comment")
|
.getFunction("comment")
|
||||||
.sendQuery(
|
.selectOne(
|
||||||
"reference" to comment.target.reference,
|
"reference" to comment.target.reference,
|
||||||
"resource" to comment
|
"resource" to comment
|
||||||
)
|
)!!
|
||||||
}
|
|
||||||
|
|
||||||
fun <I : T> edit(comment: CommentForUpdate<I, CitizenCreatorI>) {
|
fun <I : T> edit(comment: CommentForUpdate<I, CitizenCreatorI>): CommentForView<TargetRef, CitizenCreator> {
|
||||||
requester
|
return requester
|
||||||
.getFunction("edit_comment")
|
.getFunction("edit_comment")
|
||||||
.sendQuery(
|
.selectOne(
|
||||||
"id" to comment.id,
|
"id" to comment.id,
|
||||||
"content" to comment.content
|
"content" to comment.content
|
||||||
)
|
)!!
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
package fr.dcproject.component.comment.generic.routes
|
||||||
|
|
||||||
|
import fr.dcproject.application.http.badRequestIfNotValid
|
||||||
|
import fr.dcproject.common.security.assert
|
||||||
|
import fr.dcproject.common.utils.receiveOrBadRequest
|
||||||
|
import fr.dcproject.component.auth.citizen
|
||||||
|
import fr.dcproject.component.auth.citizenOrNull
|
||||||
|
import fr.dcproject.component.auth.mustBeAuth
|
||||||
|
import fr.dcproject.component.comment.generic.CommentAccessControl
|
||||||
|
import fr.dcproject.component.comment.generic.database.CommentForUpdate
|
||||||
|
import fr.dcproject.component.comment.generic.database.CommentRef
|
||||||
|
import fr.dcproject.component.comment.generic.database.CommentRepository
|
||||||
|
import fr.dcproject.component.comment.toOutput
|
||||||
|
import io.konform.validation.Validation
|
||||||
|
import io.konform.validation.jsonschema.maxLength
|
||||||
|
import io.konform.validation.jsonschema.minLength
|
||||||
|
import io.ktor.application.call
|
||||||
|
import io.ktor.features.NotFoundException
|
||||||
|
import io.ktor.http.HttpStatusCode
|
||||||
|
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||||
|
import io.ktor.locations.Location
|
||||||
|
import io.ktor.locations.post
|
||||||
|
import io.ktor.response.respond
|
||||||
|
import io.ktor.routing.Route
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
|
@KtorExperimentalLocationsAPI
|
||||||
|
object CreateComment {
|
||||||
|
@Location("/comments/{comment}")
|
||||||
|
class CreateCommentRequest(comment: UUID) {
|
||||||
|
val comment = CommentRef(comment)
|
||||||
|
class Input(val content: String) {
|
||||||
|
fun validate() = Validation<Input> {
|
||||||
|
Input::content {
|
||||||
|
minLength(20)
|
||||||
|
maxLength(6000)
|
||||||
|
}
|
||||||
|
}.validate(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Route.createCommentChildren(repo: CommentRepository, ac: CommentAccessControl) {
|
||||||
|
post<CreateCommentRequest> {
|
||||||
|
mustBeAuth()
|
||||||
|
|
||||||
|
call.receiveOrBadRequest<CreateCommentRequest.Input>()
|
||||||
|
.apply { validate().badRequestIfNotValid() }
|
||||||
|
.run {
|
||||||
|
val parent = repo.findById(it.comment.id) ?: throw NotFoundException("Comment not found")
|
||||||
|
CommentForUpdate(
|
||||||
|
content = content,
|
||||||
|
createdBy = citizen,
|
||||||
|
target = parent.target,
|
||||||
|
parent = parent,
|
||||||
|
)
|
||||||
|
}.let { newComment ->
|
||||||
|
ac.assert { canCreate(newComment, citizenOrNull) }
|
||||||
|
repo.comment(newComment)
|
||||||
|
call.respond(HttpStatusCode.Created, newComment.toOutput())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
package fr.dcproject.component.comment.generic.routes
|
|
||||||
|
|
||||||
import fr.dcproject.common.security.assert
|
|
||||||
import fr.dcproject.common.utils.receiveOrBadRequest
|
|
||||||
import fr.dcproject.component.auth.citizen
|
|
||||||
import fr.dcproject.component.auth.citizenOrNull
|
|
||||||
import fr.dcproject.component.auth.mustBeAuth
|
|
||||||
import fr.dcproject.component.comment.generic.CommentAccessControl
|
|
||||||
import fr.dcproject.component.comment.generic.database.CommentForUpdate
|
|
||||||
import fr.dcproject.component.comment.generic.database.CommentRef
|
|
||||||
import fr.dcproject.component.comment.generic.database.CommentRepository
|
|
||||||
import fr.dcproject.component.comment.toOutput
|
|
||||||
import io.ktor.application.call
|
|
||||||
import io.ktor.features.NotFoundException
|
|
||||||
import io.ktor.http.HttpStatusCode
|
|
||||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
|
||||||
import io.ktor.locations.Location
|
|
||||||
import io.ktor.locations.post
|
|
||||||
import io.ktor.response.respond
|
|
||||||
import io.ktor.routing.Route
|
|
||||||
import java.util.UUID
|
|
||||||
|
|
||||||
@KtorExperimentalLocationsAPI
|
|
||||||
object CreateCommentChildren {
|
|
||||||
@Location("/comments/{comment}/children")
|
|
||||||
class CreateCommentChildrenRequest(comment: UUID) {
|
|
||||||
val comment = CommentRef(comment)
|
|
||||||
class Input(val content: String)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun Route.createCommentChildren(repo: CommentRepository, ac: CommentAccessControl) {
|
|
||||||
post<CreateCommentChildrenRequest> {
|
|
||||||
mustBeAuth()
|
|
||||||
val parent = repo.findById(it.comment.id) ?: throw NotFoundException("Comment not found")
|
|
||||||
val newComment = CommentForUpdate(
|
|
||||||
content = call.receiveOrBadRequest<CreateCommentChildrenRequest.Input>().content,
|
|
||||||
createdBy = citizen,
|
|
||||||
parent = parent
|
|
||||||
)
|
|
||||||
|
|
||||||
ac.assert { canCreate(newComment, citizenOrNull) }
|
|
||||||
repo.comment(newComment)
|
|
||||||
|
|
||||||
call.respond(HttpStatusCode.Created, newComment.toOutput())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,14 +1,18 @@
|
|||||||
package fr.dcproject.component.comment.generic.routes
|
package fr.dcproject.component.comment.generic.routes
|
||||||
|
|
||||||
import fr.dcproject.common.response.toOutput
|
import fr.dcproject.application.http.badRequestIfNotValid
|
||||||
import fr.dcproject.common.security.assert
|
import fr.dcproject.common.security.assert
|
||||||
import fr.dcproject.common.utils.receiveOrBadRequest
|
import fr.dcproject.common.utils.receiveOrBadRequest
|
||||||
import fr.dcproject.component.auth.citizenOrNull
|
import fr.dcproject.component.auth.citizenOrNull
|
||||||
import fr.dcproject.component.auth.mustBeAuth
|
import fr.dcproject.component.auth.mustBeAuth
|
||||||
import fr.dcproject.component.comment.generic.CommentAccessControl
|
import fr.dcproject.component.comment.generic.CommentAccessControl
|
||||||
|
import fr.dcproject.component.comment.generic.database.CommentForUpdate
|
||||||
import fr.dcproject.component.comment.generic.database.CommentRef
|
import fr.dcproject.component.comment.generic.database.CommentRef
|
||||||
import fr.dcproject.component.comment.generic.database.CommentRepository
|
import fr.dcproject.component.comment.generic.database.CommentRepository
|
||||||
import fr.dcproject.component.comment.toOutput
|
import fr.dcproject.component.comment.toOutput
|
||||||
|
import io.konform.validation.Validation
|
||||||
|
import io.konform.validation.jsonschema.maxLength
|
||||||
|
import io.konform.validation.jsonschema.minLength
|
||||||
import io.ktor.application.call
|
import io.ktor.application.call
|
||||||
import io.ktor.features.NotFoundException
|
import io.ktor.features.NotFoundException
|
||||||
import io.ktor.http.HttpStatusCode
|
import io.ktor.http.HttpStatusCode
|
||||||
@@ -24,22 +28,40 @@ object EditComment {
|
|||||||
@Location("/comments/{comment}")
|
@Location("/comments/{comment}")
|
||||||
class EditCommentRequest(comment: UUID) {
|
class EditCommentRequest(comment: UUID) {
|
||||||
val comment = CommentRef(comment)
|
val comment = CommentRef(comment)
|
||||||
class Input(val content: String)
|
class Input(val content: String) {
|
||||||
|
fun validate() = Validation<Input> {
|
||||||
|
Input::content {
|
||||||
|
minLength(20)
|
||||||
|
maxLength(6000)
|
||||||
|
}
|
||||||
|
}.validate(this)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Route.editComment(repo: CommentRepository, ac: CommentAccessControl) {
|
fun Route.editComment(repo: CommentRepository, ac: CommentAccessControl) {
|
||||||
put<EditCommentRequest> {
|
put<EditCommentRequest> {
|
||||||
mustBeAuth()
|
mustBeAuth()
|
||||||
val comment = repo.findById(it.comment.id) ?: throw NotFoundException("Comment not found")
|
val commentOld = repo.findById(it.comment.id) ?: throw NotFoundException("Comment not found")
|
||||||
ac.assert { canUpdate(comment, citizenOrNull) }
|
ac.assert { canUpdate(commentOld, citizenOrNull) }
|
||||||
|
|
||||||
comment.content = call.receiveOrBadRequest<EditCommentRequest.Input>().content
|
|
||||||
repo.edit(comment)
|
|
||||||
|
|
||||||
|
call.receiveOrBadRequest<EditCommentRequest.Input>()
|
||||||
|
.apply { validate().badRequestIfNotValid() }
|
||||||
|
.run {
|
||||||
|
CommentForUpdate(
|
||||||
|
id = commentOld.id,
|
||||||
|
createdBy = commentOld.createdBy,
|
||||||
|
target = commentOld.target,
|
||||||
|
parent = commentOld.parent,
|
||||||
|
content = content,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.let { repo.edit(it) }
|
||||||
|
.let {
|
||||||
call.respond(
|
call.respond(
|
||||||
HttpStatusCode.OK,
|
HttpStatusCode.OK,
|
||||||
comment.toOutput()
|
it.toOutput()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package fr.dcproject.component.comment.generic.routes
|
package fr.dcproject.component.comment.generic.routes
|
||||||
|
|
||||||
import fr.dcproject.component.comment.generic.routes.CreateCommentChildren.createCommentChildren
|
import fr.dcproject.component.comment.generic.routes.CreateComment.createCommentChildren
|
||||||
import fr.dcproject.component.comment.generic.routes.EditComment.editComment
|
import fr.dcproject.component.comment.generic.routes.EditComment.editComment
|
||||||
import fr.dcproject.component.comment.generic.routes.GetCommentChildren.getChildrenComments
|
import fr.dcproject.component.comment.generic.routes.GetCommentChildren.getChildrenComments
|
||||||
import fr.dcproject.component.comment.generic.routes.GetOneComment.getOneComment
|
import fr.dcproject.component.comment.generic.routes.GetOneComment.getOneComment
|
||||||
|
|||||||
@@ -598,6 +598,40 @@ paths:
|
|||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/CommentResponse'
|
$ref: '#/components/schemas/CommentResponse'
|
||||||
|
post:
|
||||||
|
security:
|
||||||
|
- JWTAuth: []
|
||||||
|
summary: create comment
|
||||||
|
tags:
|
||||||
|
- comment
|
||||||
|
requestBody:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
required:
|
||||||
|
- content
|
||||||
|
properties:
|
||||||
|
content:
|
||||||
|
type: string
|
||||||
|
example:
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||||
|
responses:
|
||||||
|
201:
|
||||||
|
description: Return updated comment
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/CommentResponse'
|
||||||
|
400:
|
||||||
|
description: BadReqest
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/400'
|
||||||
|
401:
|
||||||
|
$ref: '#/components/responses/401'
|
||||||
|
404:
|
||||||
|
description: No comment found
|
||||||
put:
|
put:
|
||||||
security:
|
security:
|
||||||
- JWTAuth: []
|
- JWTAuth: []
|
||||||
@@ -614,7 +648,7 @@ paths:
|
|||||||
content:
|
content:
|
||||||
type: string
|
type: string
|
||||||
example:
|
example:
|
||||||
Lorem ipsum...
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||||
responses:
|
responses:
|
||||||
200:
|
200:
|
||||||
description: Return updated comment
|
description: Return updated comment
|
||||||
@@ -622,6 +656,12 @@ paths:
|
|||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/CommentResponse'
|
$ref: '#/components/schemas/CommentResponse'
|
||||||
|
400:
|
||||||
|
description: BadReqest
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/400'
|
||||||
401:
|
401:
|
||||||
$ref: '#/components/responses/401'
|
$ref: '#/components/responses/401'
|
||||||
/comments/{comment}/children:
|
/comments/{comment}/children:
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
create or replace function comment(reference regclass, resource json, out _id uuid)
|
create or replace function comment(reference regclass, inout resource json)
|
||||||
language plpgsql as
|
language plpgsql as
|
||||||
$$
|
$$
|
||||||
declare
|
declare
|
||||||
@@ -17,7 +17,8 @@ begin
|
|||||||
else
|
else
|
||||||
raise exception 'comment with target as "%", is not implemented', reference::text;
|
raise exception 'comment with target as "%", is not implemented', reference::text;
|
||||||
end if;
|
end if;
|
||||||
_id = _new_id;
|
|
||||||
|
select find_comment_by_id(_new_id) into resource;
|
||||||
end;
|
end;
|
||||||
$$;
|
$$;
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
create or replace function edit_comment(_id uuid, _content text) returns void
|
create or replace function edit_comment(_id uuid, _content text, out resource json)
|
||||||
language plpgsql as
|
language plpgsql as
|
||||||
$$
|
$$
|
||||||
begin
|
begin
|
||||||
update comment c set
|
update comment c set
|
||||||
"content" = _content
|
"content" = _content
|
||||||
where c.id = _id;
|
where c.id = _id;
|
||||||
|
|
||||||
|
select find_comment_by_id(_id) into resource;
|
||||||
end;
|
end;
|
||||||
$$;
|
$$;
|
||||||
|
|||||||
@@ -2,16 +2,20 @@ package integration
|
|||||||
|
|
||||||
import fr.dcproject.component.citizen.database.CitizenI
|
import fr.dcproject.component.citizen.database.CitizenI
|
||||||
import integration.steps.`when`.`When I send a GET request`
|
import integration.steps.`when`.`When I send a GET request`
|
||||||
|
import integration.steps.`when`.`When I send a POST request`
|
||||||
import integration.steps.`when`.`When I send a PUT request`
|
import integration.steps.`when`.`When I send a PUT request`
|
||||||
import integration.steps.`when`.`with body`
|
import integration.steps.`when`.`with body`
|
||||||
import integration.steps.given.`Given I have article`
|
import integration.steps.given.`Given I have article`
|
||||||
import integration.steps.given.`Given I have citizen`
|
import integration.steps.given.`Given I have citizen`
|
||||||
import integration.steps.given.`Given I have comment on article`
|
import integration.steps.given.`Given I have comment on article`
|
||||||
|
import integration.steps.given.`Given I have comment on comment`
|
||||||
import integration.steps.given.`authenticated as`
|
import integration.steps.given.`authenticated as`
|
||||||
import integration.steps.then.`And the response should contain`
|
import integration.steps.then.`And the response should contain`
|
||||||
import integration.steps.then.`And the response should not be null`
|
import integration.steps.then.`And the response should not be null`
|
||||||
import integration.steps.then.`Then the response should be`
|
import integration.steps.then.`Then the response should be`
|
||||||
import integration.steps.then.and
|
import integration.steps.then.and
|
||||||
|
import io.ktor.http.HttpStatusCode.Companion.BadRequest
|
||||||
|
import io.ktor.http.HttpStatusCode.Companion.Created
|
||||||
import io.ktor.http.HttpStatusCode.Companion.OK
|
import io.ktor.http.HttpStatusCode.Companion.OK
|
||||||
import org.junit.jupiter.api.Tag
|
import org.junit.jupiter.api.Tag
|
||||||
import org.junit.jupiter.api.Tags
|
import org.junit.jupiter.api.Tags
|
||||||
@@ -35,27 +39,105 @@ class `Comment routes` : BaseTest() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `I can create comment`() {
|
||||||
|
withIntegrationApplication {
|
||||||
|
`Given I have citizen`("Hubert", "Reeves")
|
||||||
|
`Given I have comment on comment`(id = "49933147-fc0f-4e5c-aa8d-f77fa0d88fa6")
|
||||||
|
`When I send a POST request`("/comments/49933147-fc0f-4e5c-aa8d-f77fa0d88fa6") {
|
||||||
|
`authenticated as`("Hubert", "Reeves")
|
||||||
|
`with body`(
|
||||||
|
"""
|
||||||
|
{
|
||||||
|
"content": "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
} `Then the response should be` Created and {
|
||||||
|
`And the response should not be null`()
|
||||||
|
`And the response should contain`("$.content", "Lorem ipsum dolor sit amet, consectetur adipiscing elit.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Tag("BadRequest")
|
||||||
|
fun `I cannot create comment with bad request`() {
|
||||||
|
withIntegrationApplication {
|
||||||
|
`Given I have citizen`("Hubert", "Reeves")
|
||||||
|
`Given I have comment on comment`(id = "49933147-fc0f-4e5c-aa8d-f77fa0d88fa6")
|
||||||
|
`When I send a POST request`("/comments/49933147-fc0f-4e5c-aa8d-f77fa0d88fa6") {
|
||||||
|
`authenticated as`("Hubert", "Reeves")
|
||||||
|
`with body`(
|
||||||
|
"""
|
||||||
|
{
|
||||||
|
"content": "small content"
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
} `Then the response should be` BadRequest and {
|
||||||
|
`And the response should not be null`()
|
||||||
|
`And the response should contain`("$.invalidParams[0].name", ".content")
|
||||||
|
`And the response should contain`("$.invalidParams[0].reason", "must have at least 20 characters")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `I can edit comment`() {
|
fun `I can edit comment`() {
|
||||||
withIntegrationApplication {
|
withIntegrationApplication {
|
||||||
`Given I have citizen`("Hubert", "Reeves")
|
`Given I have citizen`("Hubert", "Reeves")
|
||||||
`Given I have article`(id = "bb05e4a3-55a1-4088-85e7-8d8c23be29b1")
|
`Given I have article`(id = "bb05e4a3-55a1-4088-85e7-8d8c23be29b1")
|
||||||
`Given I have comment on article`(article = "bb05e4a3-55a1-4088-85e7-8d8c23be29b1", createdBy = CitizenI.Name(
|
`Given I have comment on article`(
|
||||||
|
article = "bb05e4a3-55a1-4088-85e7-8d8c23be29b1",
|
||||||
|
createdBy = CitizenI.Name(
|
||||||
"Hubert",
|
"Hubert",
|
||||||
"Reeves"
|
"Reeves"
|
||||||
), id = "fd30d20f-656c-42c6-8955-f61c04537464")
|
),
|
||||||
|
id = "fd30d20f-656c-42c6-8955-f61c04537464"
|
||||||
|
)
|
||||||
`When I send a PUT request`("/comments/fd30d20f-656c-42c6-8955-f61c04537464") {
|
`When I send a PUT request`("/comments/fd30d20f-656c-42c6-8955-f61c04537464") {
|
||||||
`authenticated as`("Hubert", "Reeves")
|
`authenticated as`("Hubert", "Reeves")
|
||||||
`with body`(
|
`with body`(
|
||||||
"""
|
"""
|
||||||
{
|
{
|
||||||
"content": "Hello boy"
|
"content": "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
} `Then the response should be` OK and {
|
} `Then the response should be` OK and {
|
||||||
`And the response should not be null`()
|
`And the response should not be null`()
|
||||||
`And the response should contain`("$.content", "Hello boy")
|
`And the response should contain`("$.content", "Lorem ipsum dolor sit amet, consectetur adipiscing elit.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `I cannot edit comment with bad request`() {
|
||||||
|
withIntegrationApplication {
|
||||||
|
`Given I have citizen`("Hubert", "Reeves")
|
||||||
|
`Given I have article`(id = "bb05e4a3-55a1-4088-85e7-8d8c23be29b1")
|
||||||
|
`Given I have comment on article`(
|
||||||
|
article = "bb05e4a3-55a1-4088-85e7-8d8c23be29b1",
|
||||||
|
createdBy = CitizenI.Name(
|
||||||
|
"Hubert",
|
||||||
|
"Reeves"
|
||||||
|
),
|
||||||
|
id = "fd30d20f-656c-42c6-8955-f61c04537464"
|
||||||
|
)
|
||||||
|
`When I send a PUT request`("/comments/fd30d20f-656c-42c6-8955-f61c04537464") {
|
||||||
|
`authenticated as`("Hubert", "Reeves")
|
||||||
|
`with body`(
|
||||||
|
"""
|
||||||
|
{
|
||||||
|
"content": "small content"
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
} `Then the response should be` BadRequest and {
|
||||||
|
`And the response should not be null`()
|
||||||
|
`And the response should contain`("$.invalidParams[0].name", ".content")
|
||||||
|
`And the response should contain`("$.invalidParams[0].reason", "must have at least 20 characters")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,11 +2,16 @@ package integration.steps.given
|
|||||||
|
|
||||||
import com.thedeanda.lorem.LoremIpsum
|
import com.thedeanda.lorem.LoremIpsum
|
||||||
import fr.dcproject.common.entity.TargetI
|
import fr.dcproject.common.entity.TargetI
|
||||||
|
import fr.dcproject.common.entity.TargetRef
|
||||||
import fr.dcproject.common.utils.toUUID
|
import fr.dcproject.common.utils.toUUID
|
||||||
import fr.dcproject.component.article.database.ArticleRef
|
import fr.dcproject.component.article.database.ArticleRef
|
||||||
import fr.dcproject.component.article.database.ArticleRepository
|
import fr.dcproject.component.article.database.ArticleRepository
|
||||||
|
import fr.dcproject.component.citizen.database.CitizenCreator
|
||||||
import fr.dcproject.component.citizen.database.CitizenI.Name
|
import fr.dcproject.component.citizen.database.CitizenI.Name
|
||||||
import fr.dcproject.component.comment.generic.database.CommentForUpdate
|
import fr.dcproject.component.comment.generic.database.CommentForUpdate
|
||||||
|
import fr.dcproject.component.comment.generic.database.CommentForView
|
||||||
|
import fr.dcproject.component.comment.generic.database.CommentI
|
||||||
|
import fr.dcproject.component.comment.generic.database.CommentRef
|
||||||
import fr.dcproject.component.comment.generic.database.CommentRepository
|
import fr.dcproject.component.comment.generic.database.CommentRepository
|
||||||
import fr.dcproject.component.constitution.database.ConstitutionRef
|
import fr.dcproject.component.constitution.database.ConstitutionRef
|
||||||
import fr.dcproject.component.constitution.database.ConstitutionRepository
|
import fr.dcproject.component.constitution.database.ConstitutionRepository
|
||||||
@@ -32,14 +37,14 @@ fun TestApplicationEngine.`Given I have comments on article`(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createComment(
|
fun <A : ArticleRef> createComment(
|
||||||
id: UUID? = null,
|
id: UUID? = null,
|
||||||
article: ArticleRef? = null,
|
article: A? = null,
|
||||||
createdBy: Name? = null,
|
createdBy: Name? = null,
|
||||||
content: String? = null
|
content: String? = null
|
||||||
) {
|
): CommentForView<TargetRef, CitizenCreator> {
|
||||||
val articleRepository: ArticleRepository by lazy { GlobalContext.get().koin.get() }
|
val articleRepository: ArticleRepository by lazy { GlobalContext.get().koin.get() }
|
||||||
createCommentOnTarget(
|
return createCommentOnTarget(
|
||||||
id,
|
id,
|
||||||
article?.id?.let { articleRepository.findById(article.id) } ?: createArticle(article?.id),
|
article?.id?.let { articleRepository.findById(article.id) } ?: createArticle(article?.id),
|
||||||
createdBy,
|
createdBy,
|
||||||
@@ -56,14 +61,14 @@ fun TestApplicationEngine.`Given I have comment on constitution`(
|
|||||||
createComment(id?.toUUID(), ConstitutionRef(constitution?.toUUID()), createdBy, content)
|
createComment(id?.toUUID(), ConstitutionRef(constitution?.toUUID()), createdBy, content)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createComment(
|
fun <C : ConstitutionRef> createComment(
|
||||||
id: UUID? = null,
|
id: UUID? = null,
|
||||||
constitution: ConstitutionRef? = null,
|
constitution: C? = null,
|
||||||
createdBy: Name? = null,
|
createdBy: Name? = null,
|
||||||
content: String? = null
|
content: String? = null
|
||||||
) {
|
): CommentForView<TargetRef, CitizenCreator> {
|
||||||
val constitutionRepository: ConstitutionRepository by lazy { GlobalContext.get().koin.get() }
|
val constitutionRepository: ConstitutionRepository by lazy { GlobalContext.get().koin.get() }
|
||||||
createCommentOnTarget(
|
return createCommentOnTarget(
|
||||||
id,
|
id,
|
||||||
constitution?.id?.let { constitutionRepository.findById(constitution.id) } ?: createConstitution(constitution?.id),
|
constitution?.id?.let { constitutionRepository.findById(constitution.id) } ?: createConstitution(constitution?.id),
|
||||||
createdBy,
|
createdBy,
|
||||||
@@ -71,12 +76,12 @@ fun createComment(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createCommentOnTarget(
|
fun <T : TargetI> createCommentOnTarget(
|
||||||
id: UUID? = null,
|
id: UUID? = null,
|
||||||
target: TargetI,
|
target: T,
|
||||||
createdBy: Name? = null,
|
createdBy: Name? = null,
|
||||||
content: String? = null
|
content: String? = null
|
||||||
) {
|
): CommentForView<TargetRef, CitizenCreator> {
|
||||||
val commentRepository: CommentRepository by lazy { GlobalContext.get().koin.get() }
|
val commentRepository: CommentRepository by lazy { GlobalContext.get().koin.get() }
|
||||||
val creator = createCitizen(createdBy)
|
val creator = createCitizen(createdBy)
|
||||||
val comment = CommentForUpdate(
|
val comment = CommentForUpdate(
|
||||||
@@ -85,5 +90,41 @@ fun createCommentOnTarget(
|
|||||||
target = target,
|
target = target,
|
||||||
content = content ?: LoremIpsum().getParagraphs(1, 3)
|
content = content ?: LoremIpsum().getParagraphs(1, 3)
|
||||||
)
|
)
|
||||||
commentRepository.comment(comment)
|
return commentRepository.comment(comment)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun TestApplicationEngine.`Given I have comment on comment`(
|
||||||
|
id: String? = null,
|
||||||
|
parent: String? = null,
|
||||||
|
createdBy: Name? = null,
|
||||||
|
content: String? = null,
|
||||||
|
): CommentForView<out TargetRef, CitizenCreator> {
|
||||||
|
return createCommentOnComment(
|
||||||
|
id?.toUUID() ?: UUID.randomUUID(),
|
||||||
|
parent?.run { CommentRef(toUUID()) },
|
||||||
|
createdBy,
|
||||||
|
content,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createCommentOnComment(
|
||||||
|
id: UUID? = null,
|
||||||
|
parent: CommentI? = createComment<ArticleRef>(),
|
||||||
|
createdBy: Name? = null,
|
||||||
|
content: String? = null
|
||||||
|
): CommentForView<out TargetRef, CitizenCreator> {
|
||||||
|
val creator = createCitizen(createdBy)
|
||||||
|
val commentRepository: CommentRepository by lazy { GlobalContext.get().koin.get() }
|
||||||
|
val parentComment = if (parent == null) {
|
||||||
|
createComment<ArticleRef>()
|
||||||
|
} else {
|
||||||
|
commentRepository.findById(parent.id) ?: error("Parent of comment not found")
|
||||||
|
}
|
||||||
|
val comment = CommentForUpdate(
|
||||||
|
id = id ?: UUID.randomUUID(),
|
||||||
|
createdBy = creator,
|
||||||
|
content = content ?: LoremIpsum().getParagraphs(1, 3),
|
||||||
|
parent = parentComment,
|
||||||
|
)
|
||||||
|
return commentRepository.comment(comment)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user