Big refactoring #77

Merged
flecomte merged 166 commits from refactoring-component-and-immutable into master 2021-03-24 19:06:07 +01:00
8 changed files with 245 additions and 26 deletions
Showing only changes of commit e8716a1e7f - Show all commits

View File

@@ -0,0 +1,97 @@
package integration
import integration.asserts.`And have property`
import integration.asserts.`And the response should not be null`
import integration.asserts.`Then the response should be`
import integration.asserts.`when`.`When I send a GET request`
import integration.asserts.`when`.`When I send a POST request`
import integration.asserts.`whish contains`
import integration.asserts.and
import integration.asserts.given.`Given I have article created by workgroup`
import integration.asserts.given.`Given I have article`
import integration.asserts.given.`Given I have articles`
import integration.asserts.given.`Given I have citizen`
import integration.asserts.given.`Given I have workgroup`
import integration.asserts.given.`authenticated as`
import io.ktor.http.HttpStatusCode.Companion.OK
import org.junit.jupiter.api.Tag
import org.junit.jupiter.api.Tags
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.TestInstance
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@Tags(Tag("integration"), Tag("citizen"))
class `Article routes` : BaseTest() {
@Test
fun `I can get article list`() {
withIntegrationApplication {
`Given I have articles`(3)
`When I send a GET request`("/articles") `Then the response should be` OK and {
`And the response should not be null`
}
}
}
@Test
fun `I can get articles filtered by workgroup`() {
withIntegrationApplication {
`Given I have articles`(3)
`Given I have workgroup`(name = "Les papy", id = "2bccd5a7-9082-4b31-88f8-e25d70b22b12")
`Given I have article created by workgroup`("2bccd5a7-9082-4b31-88f8-e25d70b22b12")
`When I send a GET request`("/articles?workgroup=2bccd5a7-9082-4b31-88f8-e25d70b22b12") `Then the response should be` OK and {
`And the response should not be null`
`And have property`("$.total") `whish contains` 1
`And have property`("$.result[0]workgroup.name") `whish contains` "Les papy"
}
}
}
@Test
fun `I can get versions of article by the id`() {
withIntegrationApplication {
`Given I have article`(id = "13e6091c-8fed-4600-b079-a97a6b7a9800")
`When I send a GET request`("/articles/13e6091c-8fed-4600-b079-a97a6b7a9800/versions") `Then the response should be` OK and {
`And the response should not be null`
`And have property`("$.total") `whish contains` 1
`And have property`("$.result[0].id") `whish contains` "13e6091c-8fed-4600-b079-a97a6b7a9800"
}
}
}
@Test
fun `I can get article by id`() {
withIntegrationApplication {
`Given I have article`(id = "65cda9f3-8991-4420-8d41-1da9da72c9bb")
`When I send a GET request`("/articles/65cda9f3-8991-4420-8d41-1da9da72c9bb") `Then the response should be` OK and {
`And the response should not be null`
`And have property`("$.id") `whish contains` "65cda9f3-8991-4420-8d41-1da9da72c9bb"
}
}
}
@Test
fun `I can create an article`() {
withIntegrationApplication {
`Given I have citizen`("John", "Doe")
`When I send a POST request`("/articles") {
`authenticated as`("John", "Doe")
"""
{
"version_id": "09c418b6-63ba-448b-b38b-502b41cd500e",
"title": "title2",
"annonymous": false,
"content": "content2",
"description": "description2",
"tags": [
"green"
]
}
"""
} `Then the response should be` OK and {
`And the response should not be null`
`And have property`("$.version_id") `whish contains` "09c418b6-63ba-448b-b38b-502b41cd500e"
`And have property`("$.title") `whish contains` "title2"
}
}
}
}

View File

@@ -14,7 +14,6 @@ import io.ktor.util.KtorExperimentalAPI
import io.lettuce.core.RedisClient import io.lettuce.core.RedisClient
import io.lettuce.core.api.sync.RedisCommands import io.lettuce.core.api.sync.RedisCommands
import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.isActive
import org.junit.jupiter.api.AfterAll import org.junit.jupiter.api.AfterAll
import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.BeforeAll import org.junit.jupiter.api.BeforeAll
@@ -22,9 +21,6 @@ import org.junit.jupiter.api.BeforeEach
import org.koin.test.KoinTest import org.koin.test.KoinTest
import org.koin.test.get import org.koin.test.get
@ExperimentalCoroutinesApi
@KtorExperimentalAPI
@KtorExperimentalLocationsAPI
abstract class BaseTest : KoinTest { abstract class BaseTest : KoinTest {
companion object { companion object {
private var init = false private var init = false
@@ -44,6 +40,9 @@ abstract class BaseTest : KoinTest {
return engine.test() return engine.test()
} }
@ExperimentalCoroutinesApi
@KtorExperimentalAPI
@KtorExperimentalLocationsAPI
@BeforeAll @BeforeAll
fun before() { fun before() {
engine.start() engine.start()

View File

@@ -1,6 +1,5 @@
package integration package integration
import integration.BaseTest
import integration.asserts.`And have property` import integration.asserts.`And have property`
import integration.asserts.`And the response should not be null` import integration.asserts.`And the response should not be null`
import integration.asserts.`Then the response should be` import integration.asserts.`Then the response should be`
@@ -13,17 +12,11 @@ import integration.asserts.given.`authenticated as`
import io.ktor.http.HttpStatusCode.Companion.BadRequest import io.ktor.http.HttpStatusCode.Companion.BadRequest
import io.ktor.http.HttpStatusCode.Companion.Created import io.ktor.http.HttpStatusCode.Companion.Created
import io.ktor.http.HttpStatusCode.Companion.OK import io.ktor.http.HttpStatusCode.Companion.OK
import io.ktor.locations.KtorExperimentalLocationsAPI
import io.ktor.util.KtorExperimentalAPI
import kotlinx.coroutines.ExperimentalCoroutinesApi
import org.junit.jupiter.api.Tag import org.junit.jupiter.api.Tag
import org.junit.jupiter.api.Tags import org.junit.jupiter.api.Tags
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
import org.junit.jupiter.api.TestInstance import org.junit.jupiter.api.TestInstance
@ExperimentalCoroutinesApi
@KtorExperimentalLocationsAPI
@KtorExperimentalAPI
@TestInstance(TestInstance.Lifecycle.PER_CLASS) @TestInstance(TestInstance.Lifecycle.PER_CLASS)
@Tags(Tag("integration"), Tag("citizen")) @Tags(Tag("integration"), Tag("citizen"))
class `Citizen routes` : BaseTest() { class `Citizen routes` : BaseTest() {

View File

@@ -1,6 +1,5 @@
package integration package integration
import integration.BaseTest
import integration.asserts.`And the response should not be null` import integration.asserts.`And the response should not be null`
import integration.asserts.`Then the response should be` import integration.asserts.`Then the response should be`
import integration.asserts.`and should contains` import integration.asserts.`and should contains`
@@ -9,17 +8,11 @@ import integration.asserts.given.`Given I have citizen`
import integration.asserts.given.`authenticated as` import integration.asserts.given.`authenticated as`
import io.ktor.http.HttpStatusCode import io.ktor.http.HttpStatusCode
import io.ktor.http.HttpStatusCode.Companion.NoContent import io.ktor.http.HttpStatusCode.Companion.NoContent
import io.ktor.locations.KtorExperimentalLocationsAPI
import io.ktor.util.KtorExperimentalAPI
import kotlinx.coroutines.ExperimentalCoroutinesApi
import org.junit.jupiter.api.Tag import org.junit.jupiter.api.Tag
import org.junit.jupiter.api.Tags import org.junit.jupiter.api.Tags
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
import org.junit.jupiter.api.TestInstance import org.junit.jupiter.api.TestInstance
@ExperimentalCoroutinesApi
@KtorExperimentalLocationsAPI
@KtorExperimentalAPI
@TestInstance(TestInstance.Lifecycle.PER_CLASS) @TestInstance(TestInstance.Lifecycle.PER_CLASS)
@Tags(Tag("integration"), Tag("auth")) @Tags(Tag("integration"), Tag("auth"))
class `Login routes` : BaseTest() { class `Login routes` : BaseTest() {

View File

@@ -3,21 +3,14 @@ package integration
import integration.asserts.`Then the response should be` import integration.asserts.`Then the response should be`
import integration.asserts.`when`.`When I send a POST request` import integration.asserts.`when`.`When I send a POST request`
import io.ktor.http.HttpStatusCode import io.ktor.http.HttpStatusCode
import io.ktor.locations.KtorExperimentalLocationsAPI
import io.ktor.util.KtorExperimentalAPI
import kotlinx.coroutines.ExperimentalCoroutinesApi
import org.amshove.kluent.`should be null` import org.amshove.kluent.`should be null`
import org.amshove.kluent.`should contain` import org.amshove.kluent.`should contain`
import org.amshove.kluent.`should not be null` import org.amshove.kluent.`should not be null`
import org.junit.experimental.categories.Category
import org.junit.jupiter.api.Tag import org.junit.jupiter.api.Tag
import org.junit.jupiter.api.Tags import org.junit.jupiter.api.Tags
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
import org.junit.jupiter.api.TestInstance import org.junit.jupiter.api.TestInstance
@ExperimentalCoroutinesApi
@KtorExperimentalLocationsAPI
@KtorExperimentalAPI
@TestInstance(TestInstance.Lifecycle.PER_CLASS) @TestInstance(TestInstance.Lifecycle.PER_CLASS)
@Tags(Tag("integration"), Tag("auth")) @Tags(Tag("integration"), Tag("auth"))
class `Register routes` : BaseTest() { class `Register routes` : BaseTest() {

View File

@@ -40,7 +40,7 @@ infix fun TestApplicationResponse.`And have property`(path: String): Pair<JsonPa
} }
infix fun Pair<JsonPath, Any>.`whish contains`(expected: Any): Pair<JsonPath, Any> = this.apply { infix fun Pair<JsonPath, Any>.`whish contains`(expected: Any): Pair<JsonPath, Any> = this.apply {
expected `should be equal to` second second `should be equal to` expected
} }
fun TestApplicationResponse.`And the response should contain`(path: String, valueExpected: String) { fun TestApplicationResponse.`And the response should contain`(path: String, valueExpected: String) {

View File

@@ -0,0 +1,76 @@
package integration.asserts.given
import fr.dcproject.common.utils.toUUID
import fr.dcproject.component.article.ArticleForUpdate
import fr.dcproject.component.article.ArticleRepository
import fr.dcproject.component.auth.UserForCreate
import fr.dcproject.component.citizen.CitizenForCreate
import fr.dcproject.component.citizen.CitizenI
import fr.dcproject.component.citizen.CitizenRepository
import fr.dcproject.component.workgroup.WorkgroupRef
import io.ktor.server.testing.TestApplicationEngine
import org.joda.time.DateTime
import org.koin.core.context.GlobalContext
import java.util.UUID
fun TestApplicationEngine.`Given I have article`(
id: String? = null,
workgroup: WorkgroupRef? = null,
createdByUsername: String? = null
) {
createArticle(id?.toUUID(), workgroup, createdByUsername)
}
fun TestApplicationEngine.`Given I have articles`(
numbers: Int,
) {
repeat(numbers) {
createArticle()
}
}
fun TestApplicationEngine.`Given I have article created by workgroup`(
workgroupId: String,
) {
createArticle(workgroup = WorkgroupRef(workgroupId.toUUID()))
}
private fun createArticle(
id: UUID? = null,
workgroup: WorkgroupRef? = null,
createdByUsername: String? = null
) {
val username = (createdByUsername ?: "username" + UUID.randomUUID().toString())
.toLowerCase().replace(' ', '-')
val citizenRepository: CitizenRepository by lazy<CitizenRepository> { GlobalContext.get().koin.get() }
val articleRepository: ArticleRepository by lazy<ArticleRepository> { GlobalContext.get().koin.get() }
val createdBy = if (createdByUsername != null) {
citizenRepository.findByUsername(username) ?: error("Citizen not exist")
} else {
val first = "firstName" + UUID.randomUUID().toString()
val last = "lastName" + UUID.randomUUID().toString()
CitizenForCreate(
birthday = DateTime.now(),
name = CitizenI.Name(
first,
last
),
email = "$first@fakeemail.com",
user = UserForCreate(username = username, password = "azerty")
).let {
citizenRepository.insertWithUser(it) ?: error("Unable to create User")
}
}
val article = ArticleForUpdate(
id = id ?: UUID.randomUUID(),
title = "hello",
content = "bla bla bla",
description = "A super article",
createdBy = createdBy,
workgroup = workgroup,
versionId = UUID.randomUUID()
)
articleRepository.upsert(article)
}

View File

@@ -0,0 +1,68 @@
package integration.asserts.given
import fr.dcproject.common.utils.toUUID
import fr.dcproject.component.auth.UserForCreate
import fr.dcproject.component.citizen.CitizenBasic
import fr.dcproject.component.citizen.CitizenForCreate
import fr.dcproject.component.citizen.CitizenI
import fr.dcproject.component.citizen.CitizenRepository
import fr.dcproject.component.workgroup.Workgroup
import fr.dcproject.component.workgroup.WorkgroupRepository
import fr.dcproject.component.workgroup.WorkgroupWithMembersI.Member
import fr.dcproject.component.workgroup.WorkgroupWithMembersI.Member.Role.MASTER
import io.ktor.server.testing.TestApplicationEngine
import org.joda.time.DateTime
import org.koin.core.context.GlobalContext
import org.koin.test.get
import java.util.UUID
fun TestApplicationEngine.`Given I have workgroup`(
id: String? = null,
name: String? = null,
description: String? = null,
anonymous: Boolean? = null,
createdByUsername: String? = null
) {
createWorkgroup(id?.toUUID(), name, description, anonymous, createdByUsername)
}
private fun createWorkgroup(
id: UUID? = null,
name: String? = null,
description: String? = null,
anonymous: Boolean? = null,
createdByUsername: String? = null
): Workgroup<CitizenBasic> {
val username = (createdByUsername ?: "username" + UUID.randomUUID().toString())
.toLowerCase().replace(' ', '-')
val citizenRepository: CitizenRepository by lazy<CitizenRepository> { GlobalContext.get().koin.get() }
val workgroupRepository: WorkgroupRepository by lazy<WorkgroupRepository> { GlobalContext.get().koin.get() }
val creator = citizenRepository.findByUsername(username.toLowerCase().replace(' ', '-'))
?: run {
val user = UserForCreate(
username = username,
password = "azerty",
)
CitizenForCreate(
name = CitizenI.Name("Paul", "Langevin"),
email = "$username@dc-project.fr",
birthday = DateTime.now(),
user = user
).let {
citizenRepository.insertWithUser(it) ?: error("Unable to create User")
}
}
val workgroup = Workgroup(
id = id ?: UUID.randomUUID(),
name = name ?: "Les Incoruptible",
description = description ?: "La vie est notre jeux",
createdBy = creator,
anonymous = (anonymous ?: false) == true,
members = listOf(Member(creator, listOf(MASTER)))
)
return workgroupRepository.upsert(workgroup)
}