diff --git a/.idea/runConfigurations/Functional_Tests__offline_.xml b/.idea/runConfigurations/Functional_Tests__offline_.xml new file mode 100644 index 0000000..5dae781 --- /dev/null +++ b/.idea/runConfigurations/Functional_Tests__offline_.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations/Integration_Tests.xml b/.idea/runConfigurations/Integration_Tests.xml new file mode 100644 index 0000000..5129d9e --- /dev/null +++ b/.idea/runConfigurations/Integration_Tests.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations/Unit__functional_and_integration_tests.xml b/.idea/runConfigurations/Unit__functional_and_integration_tests.xml new file mode 100644 index 0000000..45efb47 --- /dev/null +++ b/.idea/runConfigurations/Unit__functional_and_integration_tests.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations/Unit_and_functional_tests.xml b/.idea/runConfigurations/Unit_and_functional_tests.xml new file mode 100644 index 0000000..ed38f6e --- /dev/null +++ b/.idea/runConfigurations/Unit_and_functional_tests.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/kotlin/integration/BaseTest.kt b/src/test/kotlin/integration/BaseTest.kt index ab11272..678c63d 100644 --- a/src/test/kotlin/integration/BaseTest.kt +++ b/src/test/kotlin/integration/BaseTest.kt @@ -50,30 +50,36 @@ abstract class BaseTest : KoinTest { return engine.test() } - public fun TestApplicationEngine.handleGetRequest(uri: String? = null, body: TestApplicationRequest.() -> String): TestApplicationCall { + public fun TestApplicationEngine.`I send a GET request`(uri: String? = null, setup: (TestApplicationRequest.() -> Unit)? = null): TestApplicationCall { val setupOveride: TestApplicationRequest.() -> Unit = { method = HttpMethod.Get if (uri != null) { this.uri = uri } addHeader(HttpHeaders.ContentType, ContentType.Application.Json.toString()) - setBody(body().trimIndent()) + setup?.let { it() } } return handleRequest(true, setupOveride) } - public fun TestApplicationEngine.handlePostRequest(uri: String? = null, body: TestApplicationRequest.() -> String): TestApplicationCall { + public fun TestApplicationEngine.`I send a POST request`(uri: String? = null, setup: (TestApplicationRequest.() -> String?)? = null): TestApplicationCall { val setupOveride: TestApplicationRequest.() -> Unit = { method = HttpMethod.Post if (uri != null) { this.uri = uri } addHeader(HttpHeaders.ContentType, ContentType.Application.Json.toString()) - setBody(body().trimIndent()) + setup?.let { it() }?.let { + setBody(it.trimIndent()) + } } return handleRequest(true, setupOveride) } + fun TestApplicationRequest.`with body`(body: String) { + setBody(body.trimIndent()) + } + @BeforeAll fun before() { if (init == false) { @@ -110,10 +116,11 @@ abstract class BaseTest : KoinTest { } -fun TestApplicationCall.`should be respond`(status: HttpStatusCode? = null, block: TestApplicationResponse.() -> Unit) { +fun TestApplicationCall.`Then the response should be`(status: HttpStatusCode? = null, block: TestApplicationResponse.() -> Unit): TestApplicationCall { if (status != null) { response.status().`should be`(status) } block(response) + return this } \ No newline at end of file diff --git a/src/test/kotlin/integration/LoginTest.kt b/src/test/kotlin/integration/auth/LoginTest.kt similarity index 69% rename from src/test/kotlin/integration/LoginTest.kt rename to src/test/kotlin/integration/auth/LoginTest.kt index 687a78c..d68a9c8 100644 --- a/src/test/kotlin/integration/LoginTest.kt +++ b/src/test/kotlin/integration/auth/LoginTest.kt @@ -1,11 +1,12 @@ -package integration +package integration.auth -import integration.prerequisite.CitizenPrerequisite +import integration.BaseTest +import integration.`Then the response should be` +import integration.prerequisite.`Given I have citizen` 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` import org.amshove.kluent.`should contain` import org.amshove.kluent.`should not be null` import org.junit.jupiter.api.Tag @@ -17,20 +18,20 @@ import org.junit.jupiter.api.TestInstance @KtorExperimentalLocationsAPI @KtorExperimentalAPI @TestInstance(TestInstance.Lifecycle.PER_CLASS) -@Tags(Tag("integration")) +@Tags(Tag("integration"), Tag("auth")) class LoginTest : BaseTest() { @Test - fun `I can login`() { + fun `I can login with username and password`() { withIntegrationApplication { - CitizenPrerequisite().createCitizen("Niels", "Bohr") - handlePostRequest("/login") { + `Given I have citizen`("Niels", "Bohr") + `I send a POST request`("/login") { """ { "username": "niels-bohr", "password": "azerty" } """ - }.`should be respond` (HttpStatusCode.OK) { + }.`Then the response should be` (HttpStatusCode.OK) { content .`should not be null`() .`should contain`("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.") diff --git a/src/test/kotlin/integration/auth/RegisterTest.kt b/src/test/kotlin/integration/auth/RegisterTest.kt new file mode 100644 index 0000000..75b3f27 --- /dev/null +++ b/src/test/kotlin/integration/auth/RegisterTest.kt @@ -0,0 +1,68 @@ +package integration.auth + +import integration.BaseTest +import integration.`Then the response should be` +import io.ktor.http.HttpStatusCode +import io.ktor.locations.KtorExperimentalLocationsAPI +import io.ktor.server.testing.setBody +import io.ktor.util.KtorExperimentalAPI +import kotlinx.coroutines.ExperimentalCoroutinesApi +import org.amshove.kluent.`should be null` +import org.amshove.kluent.`should contain` +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.Tags +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.TestInstance + +@ExperimentalCoroutinesApi +@KtorExperimentalLocationsAPI +@KtorExperimentalAPI +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +@Tags(Tag("integration"), Tag("auth")) +class RegisterTest : BaseTest() { + @Test + @Category(RegisterTest::class) + fun `I can register`() { + withIntegrationApplication { + `I send a POST request`("/register") { + """ + { + "name": {"first_name":"George", "last_name":"MICHEL"}, + "birthday": "2001-01-01", + "user":{ + "username": "george-junior", + "password": "azerty" + }, + "email": "george-junior@gmail.com" + } + """ + }.`Then the response should be` (HttpStatusCode.OK) { + content + .`should not be null`() + .`should contain`("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.") + } + } + } + + @Test + fun `I cannot register if no username was sent`() { + withIntegrationApplication { + `I send a POST request`("/register") { + """ + { + "name": {"first_name":"George2", "last_name":"MICHEL2"}, + "birthday": "2001-01-01", + "user":{ + "username": "", + "password": "" + } + } + """ + }.`Then the response should be` (HttpStatusCode.BadRequest) { + content.`should be null`() + } + } + } +} diff --git a/src/test/kotlin/integration/prerequisite/CitizenPrerequisite.kt b/src/test/kotlin/integration/prerequisite/CitizenPrerequisite.kt index 91156c7..bc30c3e 100644 --- a/src/test/kotlin/integration/prerequisite/CitizenPrerequisite.kt +++ b/src/test/kotlin/integration/prerequisite/CitizenPrerequisite.kt @@ -1,36 +1,43 @@ package integration.prerequisite +import com.auth0.jwt.JWT import fr.dcproject.component.auth.UserForCreate +import fr.dcproject.component.auth.jwt.JwtConfig import fr.dcproject.component.citizen.Citizen import fr.dcproject.component.citizen.CitizenForCreate import fr.dcproject.component.citizen.CitizenI import fr.dcproject.component.citizen.CitizenRepository +import io.ktor.http.HttpHeaders +import io.ktor.server.testing.TestApplicationEngine +import io.ktor.server.testing.TestApplicationRequest import org.joda.time.DateTime import org.koin.core.KoinComponent +import org.koin.core.context.GlobalContext import org.koin.core.get +import org.koin.test.get +import steps.KtorServerContext import java.util.UUID -class CitizenPrerequisite : KoinComponent { - fun createCitizen( - firstName: String, - lastName: String, - email: String = ("$firstName-$lastName".toLowerCase()) + "@dc-project.fr", - id: UUID = UUID.randomUUID() - ): Citizen? { +fun TestApplicationEngine.`Given I have citizen`( + firstName: String, + lastName: String, + email: String = ("$firstName-$lastName".toLowerCase()) + "@dc-project.fr", + id: UUID = UUID.randomUUID() +): Citizen? { + val repo: CitizenRepository by lazy { GlobalContext.get().koin.get() } - val user = UserForCreate( - id = id, - username = "$firstName-$lastName".toLowerCase(), - password = "azerty", - ) - val citizen = CitizenForCreate( - id = id, - name = CitizenI.Name(firstName, lastName), - email = email, - birthday = DateTime.now(), - user = user - ) + val user = UserForCreate( + id = id, + username = "$firstName-$lastName".toLowerCase(), + password = "azerty", + ) + val citizen = CitizenForCreate( + id = id, + name = CitizenI.Name(firstName, lastName), + email = email, + birthday = DateTime.now(), + user = user + ) - return get().insertWithUser(citizen) - } + return repo.insertWithUser(citizen) }