upgrade kotlin, ktor, sendgrid

This commit is contained in:
2021-01-18 17:13:24 +01:00
parent 4b435b925e
commit a79e1ec086
69 changed files with 152 additions and 117 deletions

View File

@@ -26,7 +26,8 @@ plugins {
maven maven
id("maven-publish") id("maven-publish")
id("org.jetbrains.kotlin.jvm") version "1.3.50" kotlin("jvm") version "1.4.21"
kotlin("plugin.serialization") version "1.4.21"
id("com.github.johnrengelman.shadow") version "5.2.0" id("com.github.johnrengelman.shadow") version "5.2.0"
id("org.jlleitschuh.gradle.ktlint") version "8.2.0" id("org.jlleitschuh.gradle.ktlint") version "8.2.0"
@@ -123,6 +124,7 @@ dependencies {
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version") implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesVersion") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesVersion")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactor:$coroutinesVersion") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactor:$coroutinesVersion")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.0.1")
implementation("io.ktor:ktor-server-jetty:$ktor_version") implementation("io.ktor:ktor-server-jetty:$ktor_version")
implementation("io.ktor:ktor-client-jetty:$ktor_version") implementation("io.ktor:ktor-client-jetty:$ktor_version")
implementation("ch.qos.logback:logback-classic:$logback_version") implementation("ch.qos.logback:logback-classic:$logback_version")
@@ -139,8 +141,8 @@ dependencies {
implementation("com.auth0:java-jwt:3.12.0") implementation("com.auth0:java-jwt:3.12.0")
implementation("com.github.jasync-sql:jasync-postgresql:1.1.6") implementation("com.github.jasync-sql:jasync-postgresql:1.1.6")
implementation("com.github.flecomte:postgres-json:2.0.0") implementation("com.github.flecomte:postgres-json:2.0.0")
implementation("com.sendgrid:sendgrid-java:4.4.1") implementation("com.sendgrid:sendgrid-java:4.7.1")
implementation("io.lettuce:lettuce-core:5.3.6.RELEASE") //TODO update to 6.0.2 implementation("io.lettuce:lettuce-core:5.3.6.RELEASE") // TODO update to 6.0.2
implementation("com.rabbitmq:amqp-client:5.10.0") implementation("com.rabbitmq:amqp-client:5.10.0")
implementation("org.elasticsearch.client:elasticsearch-rest-client:6.7.1") implementation("org.elasticsearch.client:elasticsearch-rest-client:6.7.1")
implementation("com.jayway.jsonpath:json-path:2.5.0") implementation("com.jayway.jsonpath:json-path:2.5.0")

View File

@@ -1,6 +1,6 @@
ktor_version=1.2.2 ktor_version=1.5.0
kotlin.code.style=official kotlin.code.style=official
kotlin_version=1.3.40 kotlin_version=1.4.21-2
coroutinesVersion=1.4.2 coroutinesVersion=1.4.2
logback_version=1.2.3 logback_version=1.2.3
koinVersion=2.0.1 koinVersion=2.0.1

View File

@@ -49,6 +49,7 @@ import io.ktor.client.*
import io.ktor.client.engine.jetty.Jetty import io.ktor.client.engine.jetty.Jetty
import io.ktor.features.* import io.ktor.features.*
import io.ktor.http.* import io.ktor.http.*
import io.ktor.http.cio.websocket.*
import io.ktor.jackson.* import io.ktor.jackson.*
import io.ktor.locations.* import io.ktor.locations.*
import io.ktor.response.* import io.ktor.response.*
@@ -117,10 +118,12 @@ fun Application.module(env: Env = PROD) {
disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
configure(SerializationFeature.INDENT_OUTPUT, true) configure(SerializationFeature.INDENT_OUTPUT, true)
setDefaultPrettyPrinter(DefaultPrettyPrinter().apply { setDefaultPrettyPrinter(
indentArraysWith(DefaultPrettyPrinter.FixedSpaceIndenter.instance) DefaultPrettyPrinter().apply {
indentObjectsWith(DefaultIndenter(" ", "\n")) indentArraysWith(DefaultPrettyPrinter.FixedSpaceIndenter.instance)
}) indentObjectsWith(DefaultIndenter(" ", "\n"))
}
)
} }
} }

View File

@@ -1,10 +1,10 @@
package fr.dcproject.component.article package fr.dcproject.component.article
import fr.dcproject.component.citizen.*
import fr.dcproject.component.workgroup.WorkgroupCart import fr.dcproject.component.workgroup.WorkgroupCart
import fr.dcproject.component.workgroup.WorkgroupCartI import fr.dcproject.component.workgroup.WorkgroupCartI
import fr.dcproject.component.workgroup.WorkgroupRef import fr.dcproject.component.workgroup.WorkgroupRef
import fr.dcproject.component.workgroup.WorkgroupSimple import fr.dcproject.component.workgroup.WorkgroupSimple
import fr.dcproject.component.citizen.*
import fr.dcproject.entity.* import fr.dcproject.entity.*
import fr.postgresjson.entity.* import fr.postgresjson.entity.*
import org.joda.time.DateTime import org.joda.time.DateTime

View File

@@ -30,7 +30,8 @@ class ArticleRepository(override var requester: Requester) : RepositoryI {
return requester return requester
.getFunction("find_articles") .getFunction("find_articles")
.select( .select(
page, limit, page,
limit,
"sort" to sort?.toSnakeCase(), "sort" to sort?.toSnakeCase(),
"direction" to direction, "direction" to direction,
"search" to search, "search" to search,

View File

@@ -1,11 +1,11 @@
package fr.dcproject.component.article package fr.dcproject.component.article
import fr.dcproject.component.citizen.CitizenI import fr.dcproject.component.citizen.CitizenI
import fr.dcproject.component.views.ViewManager
import fr.dcproject.entity.ViewAggregation import fr.dcproject.entity.ViewAggregation
import fr.dcproject.utils.contentToString import fr.dcproject.utils.contentToString
import fr.dcproject.utils.getJsonField import fr.dcproject.utils.getJsonField
import fr.dcproject.utils.toIso import fr.dcproject.utils.toIso
import fr.dcproject.component.views.ViewManager
import org.elasticsearch.client.Request import org.elasticsearch.client.Request
import org.elasticsearch.client.Response import org.elasticsearch.client.Response
import org.elasticsearch.client.RestClient import org.elasticsearch.client.RestClient
@@ -27,7 +27,8 @@ class ArticleViewManager(private val restClient: RestClient) : ViewManager<Artic
"/views/_doc/" "/views/_doc/"
).apply { ).apply {
//language=JSON //language=JSON
setJsonEntity(""" setJsonEntity(
"""
{ {
"logged": $isLogged, "logged": $isLogged,
"type": "article", "type": "article",
@@ -38,7 +39,8 @@ class ArticleViewManager(private val restClient: RestClient) : ViewManager<Artic
"citizen_id": "${citizen?.id}", "citizen_id": "${citizen?.id}",
"view_at": "${dateTime.toIso()}" "view_at": "${dateTime.toIso()}"
} }
""".trimIndent()) """.trimIndent()
)
} }
return restClient.performRequest(request) return restClient.performRequest(request)
@@ -53,7 +55,8 @@ class ArticleViewManager(private val restClient: RestClient) : ViewManager<Artic
"/views/_search" "/views/_search"
).apply { ).apply {
//language=JSON //language=JSON
setJsonEntity(""" setJsonEntity(
"""
{ {
"size": 0, "size": 0,
"query": { "query": {
@@ -81,7 +84,8 @@ class ArticleViewManager(private val restClient: RestClient) : ViewManager<Artic
} }
} }
} }
""".trimIndent()) """.trimIndent()
)
} }
return restClient return restClient

View File

@@ -33,10 +33,10 @@ class ArticleVoter(private val articleRepo: ArticleRepository) : Voter() {
/* The new Article must by created by the same citizen of the connected citizen */ /* The new Article must by created by the same citizen of the connected citizen */
if (subject.createdBy.id == citizen.id) { if (subject.createdBy.id == citizen.id) {
/* The creator must be the same of the creator of preview version of article */ /* The creator must be the same of the creator of preview version of article */
val lastVersionId = articleRepo val lastVersionId = articleRepo
.findVersionsByVersionId(1, 1, subject.versionId) .findVersionsByVersionId(1, 1, subject.versionId)
.result .result
.firstOrNull()?.createdBy?.id .firstOrNull()?.createdBy?.id
return when (lastVersionId) { return when (lastVersionId) {
null -> granted("You can create a new Article") null -> granted("You can create a new Article")

View File

@@ -12,7 +12,8 @@ class User(
blockedAt: DateTime? = null, blockedAt: DateTime? = null,
override var plainPassword: String? = null, override var plainPassword: String? = null,
override var roles: List<Roles> = emptyList() override var roles: List<Roles> = emptyList()
) : UserFull, UserBasic(id, username, blockedAt), ) : UserFull,
UserBasic(id, username, blockedAt),
EntityCreatedAt by EntityCreatedAtImp(), EntityCreatedAt by EntityCreatedAtImp(),
EntityUpdatedAt by EntityUpdatedAtImp() EntityUpdatedAt by EntityUpdatedAtImp()

View File

@@ -33,7 +33,8 @@ class CitizenRepository(override var requester: Requester) : RepositoryI {
): Paginated<CitizenBasic> = requester ): Paginated<CitizenBasic> = requester
.getFunction("find_citizens") .getFunction("find_citizens")
.select( .select(
page, limit, page,
limit,
"sort" to sort?.toSnakeCase(), "sort" to sort?.toSnakeCase(),
"direction" to direction, "direction" to direction,
"search" to search "search" to search

View File

@@ -27,7 +27,8 @@ class CommentArticleRepository(requester: Requester) : CommentRepositoryAbs<Arti
return requester.run { return requester.run {
getFunction("find_comments_by_citizen") getFunction("find_comments_by_citizen")
.select( .select(
page, limit, page,
limit,
"created_by_id" to citizen.id, "created_by_id" to citizen.id,
"reference" to TargetI.getReference(ArticleRef::class) "reference" to TargetI.getReference(ArticleRef::class)
) )
@@ -42,7 +43,8 @@ class CommentArticleRepository(requester: Requester) : CommentRepositoryAbs<Arti
): Paginated<CommentForView<ArticleForView, CitizenRef>> = requester ): Paginated<CommentForView<ArticleForView, CitizenRef>> = requester
.getFunction("find_comments_by_target") .getFunction("find_comments_by_target")
.select( .select(
page, limit, page,
limit,
"target_id" to target.id, "target_id" to target.id,
"sort" to sort.sql "sort" to sort.sql
) )

View File

@@ -36,7 +36,8 @@ abstract class CommentRepositoryAbs<T : TargetI>(override var requester: Request
return requester.run { return requester.run {
getFunction("find_comments_by_parent") getFunction("find_comments_by_parent")
.select( .select(
page, limit, page,
limit,
"parent_id" to parentId "parent_id" to parentId
) )
} }
@@ -60,7 +61,8 @@ abstract class CommentRepositoryAbs<T : TargetI>(override var requester: Request
return requester.run { return requester.run {
getFunction("find_comments_by_target") getFunction("find_comments_by_target")
.select( .select(
page, limit, page,
limit,
"target_id" to targetId, "target_id" to targetId,
"sort" to sort.sql "sort" to sort.sql
) )
@@ -101,7 +103,8 @@ class CommentRepository(requester: Requester) : CommentRepositoryAbs<TargetRef>(
return requester.run { return requester.run {
getFunction("find_comments_by_citizen") getFunction("find_comments_by_citizen")
.select( .select(
page, limit, page,
limit,
"created_by_id" to citizen.id "created_by_id" to citizen.id
) )
} }
@@ -115,7 +118,8 @@ class CommentRepository(requester: Requester) : CommentRepositoryAbs<TargetRef>(
return requester.run { return requester.run {
getFunction("find_comments_by_parent") getFunction("find_comments_by_parent")
.select( .select(
page, limit, page,
limit,
"parent_id" to parentId "parent_id" to parentId
) )
} }

View File

@@ -9,7 +9,7 @@ object ConfigViews {
private fun waitElasticsearchIsUp(client: RestClient) { private fun waitElasticsearchIsUp(client: RestClient) {
val logger: Logger = LoggerFactory.getLogger("fr.dcproject.elasticsearch") val logger: Logger = LoggerFactory.getLogger("fr.dcproject.elasticsearch")
val request = Request("GET", "/_cluster/health") val request = Request("GET", "/_cluster/health")
repeat(5*60 / 2) { // 5 minutes repeat(5 * 60 / 2) { // 5 minutes
runCatching { runCatching {
client.performRequest(request).statusLine.statusCode client.performRequest(request).statusLine.statusCode
}.onSuccess { }.onSuccess {
@@ -74,7 +74,7 @@ object ConfigViews {
} }
} }
} }
""".trimIndent() """.trimIndent()
) )
}.let { }.let {
performRequest(it) performRequest(it)

View File

@@ -30,7 +30,8 @@ class WorkgroupRepository(override var requester: Requester) : RepositoryI {
return requester return requester
.getFunction("find_workgroups") .getFunction("find_workgroups")
.select( .select(
page, limit, page,
limit,
"sort" to sort?.toSnakeCase(), "sort" to sort?.toSnakeCase(),
"direction" to direction, "direction" to direction,
"search" to search, "search" to search,
@@ -43,8 +44,8 @@ class WorkgroupRepository(override var requester: Requester) : RepositoryI {
.selectOne("resource" to workgroup) ?: error("query 'upsert_workgroup' return null") .selectOne("resource" to workgroup) ?: error("query 'upsert_workgroup' return null")
fun <W : WorkgroupRef> delete(workgroup: W) = requester fun <W : WorkgroupRef> delete(workgroup: W) = requester
.getFunction("delete_workgroup") .getFunction("delete_workgroup")
.perform("id" to workgroup.id) .perform("id" to workgroup.id)
fun addMember(workgroup: WorkgroupI, member: Member<CitizenI>): Member<CitizenBasic>? = fun addMember(workgroup: WorkgroupI, member: Member<CitizenI>): Member<CitizenBasic>? =
addMember(workgroup, member.citizen, member.roles) addMember(workgroup, member.citizen, member.roles)

View File

@@ -32,7 +32,12 @@ object GetWorkgroups {
fun Route.getWorkgroups(repo: WorkgroupRepository, voter: WorkgroupVoter) { fun Route.getWorkgroups(repo: WorkgroupRepository, voter: WorkgroupVoter) {
get<WorkgroupsRequest> { get<WorkgroupsRequest> {
val workgroups = val workgroups =
repo.find(it.page, it.limit, it.sort, it.direction, it.search, repo.find(
it.page,
it.limit,
it.sort,
it.direction,
it.search,
WorkgroupRepository.Filter(createdById = it.createdBy, members = it.members) WorkgroupRepository.Filter(createdById = it.createdBy, members = it.members)
) )
voter.assert { canView(workgroups.result, citizenOrNull) } voter.assert { canView(workgroups.result, citizenOrNull) }

View File

@@ -41,10 +41,10 @@ object DeleteMembersOfWorkgroup {
repo.findById(it.workgroupId)?.let { workgroup -> repo.findById(it.workgroupId)?.let { workgroup ->
call.getMembersFromRequest().let { members -> call.getMembersFromRequest().let { members ->
voter.assert { canView(workgroup, citizenOrNull) } voter.assert { canView(workgroup, citizenOrNull) }
repo.removeMembers(workgroup, members) repo.removeMembers(workgroup, members)
}.let { members -> }.let { members ->
call.respond(HttpStatusCode.OK, members) call.respond(HttpStatusCode.OK, members)
} }
} ?: call.respond(HttpStatusCode.NotFound) } ?: call.respond(HttpStatusCode.NotFound)
} }
} }

View File

@@ -41,10 +41,10 @@ object UpdateMemberOfWorkgroup {
repo.findById(it.workgroupId)?.let { workgroup -> repo.findById(it.workgroupId)?.let { workgroup ->
call.getMembersFromRequest().let { members -> call.getMembersFromRequest().let { members ->
voter.assert { canUpdateMembers(workgroup, citizenOrNull) } voter.assert { canUpdateMembers(workgroup, citizenOrNull) }
repo.updateMembers(workgroup, members) repo.updateMembers(workgroup, members)
}.let { members -> }.let { members ->
call.respond(HttpStatusCode.OK, members) call.respond(HttpStatusCode.OK, members)
} }
} ?: call.respond(HttpStatusCode.NotFound) } ?: call.respond(HttpStatusCode.NotFound)
} }
} }

View File

@@ -13,12 +13,12 @@ import fr.dcproject.repository.Follow
import fr.postgresjson.serializer.deserialize import fr.postgresjson.serializer.deserialize
import io.ktor.application.* import io.ktor.application.*
import io.ktor.util.pipeline.* import io.ktor.util.pipeline.*
import io.ktor.utils.io.errors.*
import io.lettuce.core.api.async.RedisAsyncCommands import io.lettuce.core.api.async.RedisAsyncCommands
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import kotlinx.io.errors.IOException
import org.slf4j.Logger import org.slf4j.Logger
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import fr.dcproject.repository.FollowArticle as FollowArticleRepository import fr.dcproject.repository.FollowArticle as FollowArticleRepository

View File

@@ -27,7 +27,8 @@ class CommentConstitutionRepository(requester: Requester) : CommentRepositoryAbs
return requester.run { return requester.run {
getFunction("find_comments_by_citizen") getFunction("find_comments_by_citizen")
.select( .select(
page, limit, page,
limit,
"created_by_id" to citizen.id, "created_by_id" to citizen.id,
"reference" to TargetI.getReference(ConstitutionRef::class) "reference" to TargetI.getReference(ConstitutionRef::class)
) )
@@ -43,7 +44,8 @@ class CommentConstitutionRepository(requester: Requester) : CommentRepositoryAbs
return requester.run { return requester.run {
getFunction("find_comments_by_target") getFunction("find_comments_by_target")
.select( .select(
page, limit, page,
limit,
"target_id" to target.id, "target_id" to target.id,
"sort" to sort.sql "sort" to sort.sql
) )

View File

@@ -27,7 +27,8 @@ class Constitution(override var requester: Requester) : RepositoryI {
return requester return requester
.getFunction("find_constitutions") .getFunction("find_constitutions")
.select( .select(
page, limit, page,
limit,
"sort" to sort?.toSnakeCase(), "sort" to sort?.toSnakeCase(),
"direction" to direction, "direction" to direction,
"search" to search "search" to search

View File

@@ -34,7 +34,8 @@ sealed class Follow<IN : TargetRef, OUT : TargetRef>(override var requester: Req
return requester return requester
.getFunction("find_follows_by_citizen") .getFunction("find_follows_by_citizen")
.select( .select(
page, limit, page,
limit,
"created_by_id" to citizenId "created_by_id" to citizenId
) )
} }
@@ -101,7 +102,8 @@ class FollowArticle(requester: Requester) : Follow<ArticleRef, ArticleForView>(r
return requester.run { return requester.run {
getFunction("find_follows_article_by_citizen") getFunction("find_follows_article_by_citizen")
.select( .select(
page, limit, page,
limit,
"created_by_id" to citizenId "created_by_id" to citizenId
) )
} }
@@ -115,7 +117,8 @@ class FollowArticle(requester: Requester) : Follow<ArticleRef, ArticleForView>(r
return requester return requester
.getFunction("find_follows_article_by_target") .getFunction("find_follows_article_by_target")
.select( .select(
page, limit, page,
limit,
"target_id" to target.id "target_id" to target.id
) )
} }
@@ -130,7 +133,8 @@ class FollowConstitution(requester: Requester) : Follow<ConstitutionRef, Constit
return requester.run { return requester.run {
getFunction("find_follows_constitution_by_citizen") getFunction("find_follows_constitution_by_citizen")
.select( .select(
page, limit, page,
limit,
"created_by_id" to citizenId "created_by_id" to citizenId
) )
} }

View File

@@ -82,7 +82,8 @@ abstract class Opinion<T : TargetRef>(requester: Requester) : OpinionChoice(requ
return requester.run { return requester.run {
getFunction("find_citizen_opinions_by_target_ids") getFunction("find_citizen_opinions_by_target_ids")
.select( .select(
typeReference, mapOf( typeReference,
mapOf(
"citizen_id" to citizen.id, "citizen_id" to citizen.id,
"ids" to targets "ids" to targets
) )
@@ -101,7 +102,8 @@ abstract class Opinion<T : TargetRef>(requester: Requester) : OpinionChoice(requ
return requester return requester
.getFunction("find_citizen_opinions_by_target_id") .getFunction("find_citizen_opinions_by_target_id")
.select( .select(
typeReference, mapOf( typeReference,
mapOf(
"citizen_id" to citizen.id, "citizen_id" to citizen.id,
"id" to target "id" to target
) )
@@ -121,7 +123,9 @@ abstract class Opinion<T : TargetRef>(requester: Requester) : OpinionChoice(requ
): Paginated<OpinionEntity<TargetRef>> { ): Paginated<OpinionEntity<TargetRef>> {
return requester return requester
.getFunction("find_citizen_opinions") .getFunction("find_citizen_opinions")
.select(page, limit, .select(
page,
limit,
"sort" to sort?.toSnakeCase(), "sort" to sort?.toSnakeCase(),
"direction" to direction, "direction" to direction,
"citizen_id" to citizen.id "citizen_id" to citizen.id

View File

@@ -37,7 +37,10 @@ open class Vote<T : TargetI>(override var requester: Requester) : RepositoryI {
return requester.run { return requester.run {
getFunction("find_votes_by_citizen") getFunction("find_votes_by_citizen")
.select( .select(
page, limit, typeReference, mapOf( page,
limit,
typeReference,
mapOf(
"created_by_id" to citizenId, "created_by_id" to citizenId,
"reference" to target "reference" to target
) )
@@ -53,7 +56,8 @@ open class Vote<T : TargetI>(override var requester: Requester) : RepositoryI {
return requester.run { return requester.run {
getFunction("find_citizen_votes_by_target_ids") getFunction("find_citizen_votes_by_target_ids")
.select( .select(
typeReference, mapOf( typeReference,
mapOf(
"citizen_id" to citizen.id, "citizen_id" to citizen.id,
"ids" to targets "ids" to targets
) )

View File

@@ -60,7 +60,10 @@ object ConstitutionPaths {
) : UuidEntity(id) { ) : UuidEntity(id) {
fun create(): TitleSimple<ArticleRef> = fun create(): TitleSimple<ArticleRef> =
TitleSimple( TitleSimple(
id, name, rank, articles id,
name,
rank,
articles
) )
} }

View File

@@ -1,6 +1,7 @@
package steps package steps
import io.ktor.application.* import io.ktor.application.*
import io.ktor.server.engine.*
import io.ktor.server.testing.* import io.ktor.server.testing.*
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
import kotlin.test.fail import kotlin.test.fail

View File

@@ -6,11 +6,9 @@ import io.cucumber.java8.En
import io.ktor.http.* import io.ktor.http.*
import io.ktor.server.testing.* import io.ktor.server.testing.*
import io.ktor.util.* import io.ktor.util.*
import kotlinx.serialization.ImplicitReflectionSerializer
import kotlin.test.assertEquals import kotlin.test.assertEquals
import kotlin.test.assertNotEquals import kotlin.test.assertNotEquals
@ImplicitReflectionSerializer
@KtorExperimentalAPI @KtorExperimentalAPI
class KtorServerRequestSteps : En { class KtorServerRequestSteps : En {
init { init {

View File

@@ -2,17 +2,11 @@ package steps
import io.cucumber.datatable.DataTable import io.cucumber.datatable.DataTable
import io.cucumber.java8.En import io.cucumber.java8.En
import kotlinx.serialization.ImplicitReflectionSerializer import kotlinx.serialization.json.*
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonArray
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.JsonPrimitive
import kotlinx.serialization.parse
import kotlin.test.assertEquals import kotlin.test.assertEquals
import kotlin.test.assertTrue import kotlin.test.assertTrue
import kotlin.test.fail import kotlin.test.fail
@ImplicitReflectionSerializer
class KtorServerRestSteps : En { class KtorServerRestSteps : En {
init { init {
Then("the JSON should contain:") { dataTable: DataTable -> Then("the JSON should contain:") { dataTable: DataTable ->
@@ -60,7 +54,7 @@ class KtorServerRestSteps : En {
} }
private val responseJsonElement: JsonElement private val responseJsonElement: JsonElement
get() = Json.parse(KtorServerContext.defaultServer.call?.response?.content ?: fail("The response isn't valid JSON")) get() = Json.parseToJsonElement(KtorServerContext.defaultServer.call?.response?.content ?: fail("The response isn't valid JSON"))
private val response: String private val response: String
get() = KtorServerContext.defaultServer.call?.response?.content ?: fail("The response isn't valid") get() = KtorServerContext.defaultServer.call?.response?.content ?: fail("The response isn't valid")