Big refactoring #77

Merged
flecomte merged 166 commits from refactoring-component-and-immutable into master 2021-03-24 19:06:07 +01:00
46 changed files with 2 additions and 1863 deletions
Showing only changes of commit 7985ea67e5 - Show all commits

View File

@@ -25,7 +25,6 @@
<patterns> <patterns>
<pattern testClass="unit..*" /> <pattern testClass="unit..*" />
<pattern testClass="functional..*" /> <pattern testClass="functional..*" />
<pattern testClass="CucumberTest" />
<pattern testClass="integration..*" /> <pattern testClass="integration..*" />
</patterns> </patterns>
<tag value="!functional" /> <tag value="!functional" />

View File

@@ -1,24 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Article Tests" type="JUnit" factoryName="JUnit" folderName="Cucumber" show_console_on_std_err="true">
<output_file path="$PROJECT_DIR$/var/log/test/out.log" is_save="true" />
<module name="dcproject.test" />
<useClassPathOnly />
<option name="PACKAGE_NAME" value="" />
<option name="MAIN_CLASS_NAME" value="CucumberTest" />
<option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="class" />
<option name="VM_PARAMETERS" value="-ea -Dcucumber.filter.tags=&quot;@article&quot; -Dstrict" />
<option name="PARAMETERS" value="" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="wholeProject" />
</option>
<envs>
<env name="SEND_GRID_KEY" value="$SEND_GRID_KEY$" />
</envs>
<dir value="$PROJECT_DIR$" />
<tag value="!online" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>

View File

@@ -1,24 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Auth Tests" type="JUnit" factoryName="JUnit" folderName="Cucumber" show_console_on_std_err="true">
<output_file path="$PROJECT_DIR$/var/log/test/out.log" is_save="true" />
<module name="dcproject.test" />
<useClassPathOnly />
<option name="PACKAGE_NAME" value="" />
<option name="MAIN_CLASS_NAME" value="CucumberTest" />
<option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="class" />
<option name="VM_PARAMETERS" value="-ea -Dcucumber.filter.tags=&quot;@auth&quot;" />
<option name="PARAMETERS" value="" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="wholeProject" />
</option>
<envs>
<env name="SEND_GRID_KEY" value="$SEND_GRID_KEY$" />
</envs>
<dir value="$PROJECT_DIR$" />
<tag value="!online" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>

View File

@@ -1,24 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Citizen Tests" type="JUnit" factoryName="JUnit" folderName="Cucumber" show_console_on_std_err="true">
<output_file path="$PROJECT_DIR$/var/log/test/out.log" is_save="true" />
<module name="dcproject.test" />
<useClassPathOnly />
<option name="PACKAGE_NAME" value="" />
<option name="MAIN_CLASS_NAME" value="CucumberTest" />
<option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="class" />
<option name="VM_PARAMETERS" value="-ea -Dcucumber.filter.tags=&quot;@citizen&quot;" />
<option name="PARAMETERS" value="" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="wholeProject" />
</option>
<envs>
<env name="SEND_GRID_KEY" value="$SEND_GRID_KEY$" />
</envs>
<dir value="$PROJECT_DIR$" />
<tag value="!online" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>

View File

@@ -1,24 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Comment Tests" type="JUnit" factoryName="JUnit" folderName="Cucumber" show_console_on_std_err="true">
<output_file path="$PROJECT_DIR$/var/log/test/out.log" is_save="true" />
<module name="dcproject.test" />
<useClassPathOnly />
<option name="PACKAGE_NAME" value="" />
<option name="MAIN_CLASS_NAME" value="CucumberTest" />
<option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="class" />
<option name="VM_PARAMETERS" value="-ea -Dcucumber.filter.tags=&quot;@comment&quot;" />
<option name="PARAMETERS" value="" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="wholeProject" />
</option>
<envs>
<env name="SEND_GRID_KEY" value="$SEND_GRID_KEY$" />
</envs>
<dir value="$PROJECT_DIR$" />
<tag value="!online" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>

View File

@@ -1,24 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Constitution Tests" type="JUnit" factoryName="JUnit" folderName="Cucumber" show_console_on_std_err="true">
<output_file path="$PROJECT_DIR$/var/log/test/out.log" is_save="true" />
<module name="dcproject.test" />
<useClassPathOnly />
<option name="PACKAGE_NAME" value="" />
<option name="MAIN_CLASS_NAME" value="CucumberTest" />
<option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="class" />
<option name="VM_PARAMETERS" value="-ea -Dcucumber.filter.tags=&quot;@constitution&quot;" />
<option name="PARAMETERS" value="" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="wholeProject" />
</option>
<envs>
<env name="SEND_GRID_KEY" value="$SEND_GRID_KEY$" />
</envs>
<dir value="$PROJECT_DIR$" />
<tag value="!online" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>

View File

@@ -1,19 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Cucumber Tests" type="JUnit" factoryName="JUnit">
<output_file path="$PROJECT_DIR$/var/log/test/cucumber.out.log" is_save="true" />
<module name="dcproject.test" />
<useClassPathOnly />
<option name="PACKAGE_NAME" value="" />
<option name="MAIN_CLASS_NAME" value="CucumberTest" />
<option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="class" />
<option name="VM_PARAMETERS" value="-ea -Djdk.attach.allowAttachSelf=true" />
<option name="PARAMETERS" value="" />
<envs>
<env name="SEND_GRID_KEY" value="$SEND_GRID_KEY$" />
</envs>
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>

View File

@@ -1,24 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Cucumber Tests (offline)" type="JUnit" factoryName="JUnit" show_console_on_std_err="true">
<output_file path="$PROJECT_DIR$/var/log/test/out.log" is_save="true" />
<module name="dcproject.test" />
<useClassPathOnly />
<option name="PACKAGE_NAME" value="" />
<option name="MAIN_CLASS_NAME" value="CucumberTest" />
<option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="class" />
<option name="VM_PARAMETERS" value="-ea -Dcucumber.filter.tags=&quot; not @online&quot; -Djdk.attach.allowAttachSelf=true" />
<option name="PARAMETERS" value="" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="wholeProject" />
</option>
<envs>
<env name="SEND_GRID_KEY" value="$SEND_GRID_KEY$" />
</envs>
<dir value="$PROJECT_DIR$" />
<tag value="!online" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>

View File

@@ -1,24 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Cucumber with tag @now" type="JUnit" factoryName="JUnit" show_console_on_std_err="true">
<output_file path="$PROJECT_DIR$/var/log/test/out.log" is_save="true" />
<module name="dcproject.test" />
<useClassPathOnly />
<option name="PACKAGE_NAME" value="" />
<option name="MAIN_CLASS_NAME" value="CucumberTest" />
<option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="class" />
<option name="VM_PARAMETERS" value="-ea -Dcucumber.filter.tags=&quot;@now&quot; -Djdk.attach.allowAttachSelf=true" />
<option name="PARAMETERS" value="" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="wholeProject" />
</option>
<envs>
<env name="SEND_GRID_KEY" value="$SEND_GRID_KEY$" />
</envs>
<dir value="$PROJECT_DIR$" />
<tag value="!online" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>

View File

@@ -1,24 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Follow Tests" type="JUnit" factoryName="JUnit" folderName="Cucumber" show_console_on_std_err="true">
<output_file path="$PROJECT_DIR$/var/log/test/out.log" is_save="true" />
<module name="dcproject.test" />
<useClassPathOnly />
<option name="PACKAGE_NAME" value="" />
<option name="MAIN_CLASS_NAME" value="CucumberTest" />
<option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="class" />
<option name="VM_PARAMETERS" value="-ea -Dcucumber.filter.tags=&quot;@follow&quot;" />
<option name="PARAMETERS" value="" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="wholeProject" />
</option>
<envs>
<env name="SEND_GRID_KEY" value="$SEND_GRID_KEY$" />
</envs>
<dir value="$PROJECT_DIR$" />
<tag value="!online" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>

View File

@@ -2,7 +2,6 @@
<configuration default="false" name="Integration Tests" type="JUnit" factoryName="JUnit" singleton="false" show_console_on_std_err="true"> <configuration default="false" name="Integration Tests" type="JUnit" factoryName="JUnit" singleton="false" show_console_on_std_err="true">
<output_file path="$PROJECT_DIR$/var/log/test/out.log" is_save="true" /> <output_file path="$PROJECT_DIR$/var/log/test/out.log" is_save="true" />
<useClassPathOnly /> <useClassPathOnly />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="true" />
<option name="ALTERNATIVE_JRE_PATH" value="corretto-11" /> <option name="ALTERNATIVE_JRE_PATH" value="corretto-11" />
<option name="PACKAGE_NAME" value="" /> <option name="PACKAGE_NAME" value="" />
<option name="MAIN_CLASS_NAME" value="" /> <option name="MAIN_CLASS_NAME" value="" />

View File

@@ -1,24 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Mark as @error" type="JUnit" factoryName="JUnit" folderName="Cucumber" show_console_on_std_err="true">
<output_file path="$PROJECT_DIR$/var/log/test/out.log" is_save="true" />
<module name="dcproject.test" />
<useClassPathOnly />
<option name="PACKAGE_NAME" value="" />
<option name="MAIN_CLASS_NAME" value="CucumberTest" />
<option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="class" />
<option name="VM_PARAMETERS" value="-ea -Dcucumber.filter.tags=&quot;@error&quot; -Dstrict" />
<option name="PARAMETERS" value="" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="wholeProject" />
</option>
<envs>
<env name="SEND_GRID_KEY" value="$SEND_GRID_KEY$" />
</envs>
<dir value="$PROJECT_DIR$" />
<tag value="!online" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>

View File

@@ -1,24 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Opinion Tests" type="JUnit" factoryName="JUnit" folderName="Cucumber" show_console_on_std_err="true">
<output_file path="$PROJECT_DIR$/var/log/test/out.log" is_save="true" />
<module name="dcproject.test" />
<useClassPathOnly />
<option name="PACKAGE_NAME" value="" />
<option name="MAIN_CLASS_NAME" value="CucumberTest" />
<option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="class" />
<option name="VM_PARAMETERS" value="-ea -Dcucumber.filter.tags=&quot;@opinion&quot;" />
<option name="PARAMETERS" value="" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="wholeProject" />
</option>
<envs>
<env name="SEND_GRID_KEY" value="$SEND_GRID_KEY$" />
</envs>
<dir value="$PROJECT_DIR$" />
<tag value="!online" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>

View File

@@ -2,7 +2,6 @@
<configuration default="false" name="Unit and functional tests" type="JUnit" factoryName="JUnit" singleton="false" show_console_on_std_err="true"> <configuration default="false" name="Unit and functional tests" type="JUnit" factoryName="JUnit" singleton="false" show_console_on_std_err="true">
<output_file path="$PROJECT_DIR$/var/log/test/out.log" is_save="true" /> <output_file path="$PROJECT_DIR$/var/log/test/out.log" is_save="true" />
<useClassPathOnly /> <useClassPathOnly />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="true" />
<option name="ALTERNATIVE_JRE_PATH" value="corretto-11" /> <option name="ALTERNATIVE_JRE_PATH" value="corretto-11" />
<option name="PACKAGE_NAME" value="" /> <option name="PACKAGE_NAME" value="" />
<option name="MAIN_CLASS_NAME" value="" /> <option name="MAIN_CLASS_NAME" value="" />

View File

@@ -1,24 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Vote Tests" type="JUnit" factoryName="JUnit" folderName="Cucumber" show_console_on_std_err="true">
<output_file path="$PROJECT_DIR$/var/log/test/out.log" is_save="true" />
<module name="dcproject.test" />
<useClassPathOnly />
<option name="PACKAGE_NAME" value="" />
<option name="MAIN_CLASS_NAME" value="CucumberTest" />
<option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="class" />
<option name="VM_PARAMETERS" value="-ea -Dcucumber.filter.tags=&quot;@vote&quot;" />
<option name="PARAMETERS" value="" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="wholeProject" />
</option>
<envs>
<env name="SEND_GRID_KEY" value="$SEND_GRID_KEY$" />
</envs>
<dir value="$PROJECT_DIR$" />
<tag value="!online" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>

View File

@@ -1,23 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Voter Tests" type="JUnit" factoryName="JUnit" show_console_on_std_err="true">
<output_file path="$PROJECT_DIR$/var/log/test/out.log" is_save="true" />
<useClassPathOnly />
<option name="PACKAGE_NAME" value="fr.dcproject" />
<option name="MAIN_CLASS_NAME" value="" />
<option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="tags" />
<option name="VM_PARAMETERS" value="-ea -Djdk.attach.allowAttachSelf=true" />
<option name="PARAMETERS" value="" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="wholeProject" />
</option>
<envs>
<env name="SEND_GRID_KEY" value="$SEND_GRID_KEY$" />
</envs>
<dir value="$PROJECT_DIR$" />
<tag value="voter" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>

View File

@@ -1,30 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Workgroup test" type="JUnit" factoryName="JUnit" folderName="Cucumber" show_console_on_std_err="true">
<output_file path="$PROJECT_DIR$/var/log/test/out.log" is_save="true" />
<module name="dcproject.test" />
<useClassPathOnly />
<extension name="coverage" sample_coverage="false">
<pattern>
<option name="PATTERN" value="fr.dcproject.*" />
<option name="ENABLED" value="true" />
</pattern>
</extension>
<option name="PACKAGE_NAME" value="" />
<option name="MAIN_CLASS_NAME" value="CucumberTest" />
<option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="class" />
<option name="VM_PARAMETERS" value="-ea -Dcucumber.filter.tags=&quot;@workgroup&quot;" />
<option name="PARAMETERS" value="" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="wholeProject" />
</option>
<envs>
<env name="SEND_GRID_KEY" value="$SEND_GRID_KEY$" />
</envs>
<dir value="$PROJECT_DIR$" />
<tag value="!online" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>

View File

@@ -10,7 +10,6 @@ val coroutinesVersion: String by project
val logback_version: String by project val logback_version: String by project
val koinVersion: String by project val koinVersion: String by project
val jackson_version: String by project val jackson_version: String by project
val cucumber_version: String by project
group = "com.github.flecomte" group = "com.github.flecomte"
version = versioning.info.run { version = versioning.info.run {
@@ -194,8 +193,6 @@ dependencies {
testImplementation("io.mockk:mockk:1.10.5") testImplementation("io.mockk:mockk:1.10.5")
testImplementation("org.junit.jupiter:junit-jupiter:5.7.0") testImplementation("org.junit.jupiter:junit-jupiter:5.7.0")
testImplementation("org.amshove.kluent:kluent:1.61") testImplementation("org.amshove.kluent:kluent:1.61")
testImplementation("io.cucumber:cucumber-java8:$cucumber_version")
testImplementation("io.cucumber:cucumber-junit:$cucumber_version")
pitest("org.pitest:pitest-junit5-plugin:0.5") pitest("org.pitest:pitest-junit5-plugin:0.5")
testImplementation("io.mockk:mockk-agent-api:1.10.5") testImplementation("io.mockk:mockk-agent-api:1.10.5")
testImplementation("io.mockk:mockk-agent-jvm:1.10.5") testImplementation("io.mockk:mockk-agent-jvm:1.10.5")

View File

@@ -5,7 +5,6 @@ coroutinesVersion=1.4.2
logback_version=1.2.3 logback_version=1.2.3
koinVersion=2.0.1 koinVersion=2.0.1
jackson_version=2.12.1 jackson_version=2.12.1
cucumber_version=6.9.1
systemProp.sonar.host.url=http://localhost:9002 systemProp.sonar.host.url=http://localhost:9002
systemProp.sonar.login=admin systemProp.sonar.login=admin
systemProp.sonar.password=sonar systemProp.sonar.password=sonar

View File

@@ -78,7 +78,7 @@ import java.util.concurrent.CompletionException
fun main(args: Array<String>): Unit = EngineMain.main(args) fun main(args: Array<String>): Unit = EngineMain.main(args)
enum class Env { PROD, TEST, CUCUMBER } enum class Env { PROD, TEST }
@ExperimentalCoroutinesApi @ExperimentalCoroutinesApi
@KtorExperimentalAPI @KtorExperimentalAPI

View File

@@ -1,99 +0,0 @@
import com.rabbitmq.client.Channel
import com.rabbitmq.client.ConnectionFactory
import fr.dcproject.application.Configuration
import fr.dcproject.application.Env.CUCUMBER
import fr.dcproject.application.module
import fr.dcproject.common.utils.LoggerDelegate
import fr.postgresjson.connexion.Connection
import fr.postgresjson.connexion.Requester
import fr.postgresjson.migration.Migrations
import io.cucumber.java8.En
import io.cucumber.java8.Scenario
import io.cucumber.junit.Cucumber
import io.cucumber.junit.CucumberOptions
import io.ktor.server.testing.withTestApplication
import io.lettuce.core.RedisClient
import io.lettuce.core.api.sync.RedisCommands
import kotlinx.coroutines.InternalCoroutinesApi
import org.junit.runner.RunWith
import org.koin.test.KoinTest
import org.koin.test.get
import org.slf4j.Logger
import steps.KtorServerContext
var unitialized: Boolean = false
@InternalCoroutinesApi
@RunWith(Cucumber::class)
@CucumberOptions(plugin = ["pretty"], strict = true)
class CucumberTest : En, KoinTest {
private val logger: Logger? by LoggerDelegate()
val config = Configuration("application-test.conf")
val redis: RedisCommands<String, String> = RedisClient.create(config.redis).connect().sync()
val rabbit: Channel = ConnectionFactory()
.apply { setUri(config.rabbitmq) }
.newConnection()
.createChannel()
@InternalCoroutinesApi
val ktorContext = KtorServerContext {
module(CUCUMBER)
}
init {
if (!unitialized) {
withTestApplication({ module(CUCUMBER) }) {
migrations()
}
unitialized = true
}
Before(-1) { _: Scenario ->
ktorContext.start()
//language=PostgreSQL
get<Connection>().sendQuery("start transaction;", listOf())
}
After { _: Scenario ->
//language=PostgreSQL
get<Connection>().sendQuery("rollback;", listOf())
redis.flushall()
/* Purge rabbit notification queues */
rabbit.run {
queuePurge("push")
queuePurge("email")
}
ktorContext.stop()
}
}
private fun migrations() {
val migrations: Migrations = get()
migrations.forceAllDown()
migrations.run()
}
private fun fixtures() {
logger?.info("Fixtures Begin")
val connection: Connection = get()
//language=PostgreSQL
connection.sendQuery("""truncate table "user" cascade;""")
//language=PostgreSQL
connection.sendQuery("""SET fixture.quantity.multiple = '50';""")
getFixturesRequester()
.getQueries()
.sortedBy { it.name }
.forEach { it.sendQuery() }
logger?.info("Fixtures Done")
}
private fun getFixturesRequester(): Requester {
return Requester.RequesterFactory(
connection = get(),
queriesDirectory = config.sql.fixtureFiles
).createRequester()
}
}

View File

@@ -25,7 +25,7 @@ import org.junit.jupiter.api.Test
import org.junit.jupiter.api.TestInstance import org.junit.jupiter.api.TestInstance
@TestInstance(TestInstance.Lifecycle.PER_CLASS) @TestInstance(TestInstance.Lifecycle.PER_CLASS)
@Tags(Tag("integration"), Tag("vote")) @Tags(Tag("integration"), Tag("workgroup"))
class `Workgroup routes` : BaseTest() { class `Workgroup routes` : BaseTest() {
@Test @Test
fun `I can get one workgroup`() { fun `I can get one workgroup`() {

View File

@@ -1,103 +0,0 @@
package steps
import fr.dcproject.common.utils.toUUID
import fr.dcproject.component.article.ArticleForUpdate
import fr.dcproject.component.article.ArticleForView
import fr.dcproject.component.article.ArticleRepository
import fr.dcproject.component.auth.UserForCreate
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 fr.dcproject.component.comment.article.CommentArticleRepository
import fr.dcproject.component.comment.generic.CommentForUpdate
import fr.dcproject.component.workgroup.WorkgroupRef
import io.cucumber.datatable.DataTable
import io.cucumber.java8.En
import org.joda.time.DateTime
import org.koin.test.KoinTest
import org.koin.test.get
import java.util.UUID
class ArticleSteps : En, KoinTest {
init {
Given("I have {int} article") { nb: Int ->
repeat(nb) {
createArticle()
}
}
Given("I have article") { extraData: DataTable? ->
createArticle(extraData)
}
Given("I have article with ID {string}") { id: String ->
createArticle(id = UUID.fromString(id))
}
Given("I have article created by workgroup ID {string}") { id: String ->
createArticle(workgroup = WorkgroupRef(UUID.fromString(id)))
}
Given("I have comment created by {word} {word} on article {string}:") { firstName: String, lastName: String, articleId: String, extraData: DataTable? ->
commentArticle(articleId, firstName, lastName, extraData)
}
Given("I have comment created by {word} {word} on article {string}") { firstName: String, lastName: String, articleId: String ->
commentArticle(articleId, firstName, lastName)
}
}
private fun createArticle(extraData: DataTable? = null, id: UUID? = null, workgroup: WorkgroupRef? = null) {
val params = extraData?.asMap<String, String>(String::class.java, String::class.java)
val createdByUsername = params?.get("createdBy")
val username = (createdByUsername ?: "username" + UUID.randomUUID().toString())
.toLowerCase().replace(' ', '-')
val createdBy = if (createdByUsername != null) {
get<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 {
get<CitizenRepository>().insertWithUser(it) ?: error("Unable to create User")
}
}
val article = ArticleForUpdate(
id = id ?: params?.get("id")?.toUUID() ?: UUID.randomUUID(),
title = "hello",
content = "bla bla bla",
description = "A super article",
createdBy = createdBy,
workgroup = workgroup,
versionId = UUID.randomUUID()
)
get<ArticleRepository>().upsert(article)
}
private fun commentArticle(articleId: String, firstName: String, lastName: String, extraData: DataTable? = null, id: UUID? = null) {
val params = extraData?.asMap<String, String>(String::class.java, String::class.java)
val article = get<ArticleRepository>().findById(UUID.fromString(articleId)) ?: error("Article not exist")
val citizen = get<CitizenRepository>().findByUsername(
("$firstName-$lastName".toLowerCase()).toLowerCase().replace(' ', '-')
) ?: error("Citizen not exist")
val comment: CommentForUpdate<ArticleForView, Citizen> = CommentForUpdate(
id = id ?: params?.get("id")?.let { UUID.fromString(it) } ?: UUID.randomUUID(),
createdBy = citizen,
target = article,
content = params?.get("content") ?: "hello"
)
get<CommentArticleRepository>().comment(comment)
}
}

View File

@@ -1,58 +0,0 @@
package steps
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 io.cucumber.datatable.DataTable
import io.cucumber.java8.En
import org.joda.time.DateTime
import org.koin.test.KoinTest
import org.koin.test.get
import java.util.UUID
class CitizenSteps : En, KoinTest {
init {
Given("I have citizen") { extraData: DataTable? ->
val params = extraData?.asMap<String, String>(String::class.java, String::class.java)
createCitizen(
params?.get("firstName") ?: "firstName" + UUID.randomUUID(),
params?.get("lastName") ?: "lastName" + UUID.randomUUID(),
extraData
)
}
Given("I have citizen {word} {word}") { firstName: String, lastName: String ->
createCitizen(firstName, lastName)
}
Given("I have citizen {word} {word} with") { firstName: String, lastName: String, extraData: DataTable? ->
createCitizen(firstName, lastName, extraData)
}
Given("I have citizen {word} {word} with ID {string}") { firstName: String, lastName: String, id: String ->
createCitizen(firstName, lastName, id = UUID.fromString(id))
}
}
private fun createCitizen(firstName: String, lastName: String, extraData: DataTable? = null, id: UUID? = null) {
val params = extraData?.asMap<String, String>(String::class.java, String::class.java)
val id: UUID = id ?: params?.get("id")?.let { UUID.fromString(it) } ?: UUID.randomUUID()
val email = params?.get("email") ?: ("$firstName-$lastName".toLowerCase()) + "@dc-project.fr"
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
)
get<CitizenRepository>().insertWithUser(citizen)
}
}

View File

@@ -1,109 +0,0 @@
package steps
import fr.dcproject.common.utils.toUUID
import fr.dcproject.component.article.ArticleRef
import fr.dcproject.component.auth.UserForCreate
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 fr.dcproject.component.citizen.CitizenWithUserI
import fr.dcproject.component.comment.constitution.CommentConstitutionRepository
import fr.dcproject.component.comment.generic.CommentForUpdate
import fr.dcproject.component.constitution.ConstitutionRef
import fr.dcproject.component.constitution.ConstitutionRepository
import fr.dcproject.component.constitution.ConstitutionSimple
import fr.dcproject.component.constitution.ConstitutionSimple.TitleSimple
import io.cucumber.datatable.DataTable
import io.cucumber.java8.En
import org.joda.time.DateTime
import org.koin.test.KoinTest
import org.koin.test.get
import java.util.UUID
class ConstitutionSteps : En, KoinTest {
init {
Given("I have {int} constitution") { nb: Int ->
repeat(nb) {
createConstitution()
}
}
Given("I have constitution") { extraData: DataTable? ->
createConstitution(extraData)
}
Given("I have constitution with ID {string}") { id: String? ->
createConstitution(id = UUID.fromString(id))
}
Given("I have comment created by {word} {word} on constitution {string}:") { firstName: String, lastName: String, constitutionId: String, extraData: DataTable? ->
commentConstitution(constitutionId, firstName, lastName, extraData)
}
Given("I have comment created by {word} {word} on constitution {string}") { firstName: String, lastName: String, constitutionId: String ->
commentConstitution(constitutionId, firstName, lastName)
}
}
private fun createConstitution(extraData: DataTable? = null, id: UUID? = null) {
val params = extraData?.asMap<String, String>(String::class.java, String::class.java)
val createdByUsername = params?.get("createdBy")
val username = (createdByUsername ?: "username" + UUID.randomUUID().toString())
.toLowerCase().replace(' ', '-')
val createdBy = if (createdByUsername != null) {
get<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 {
get<CitizenRepository>().insertWithUser(it) ?: error("Unable to create User")
}
}
val title1 = ConstitutionSimple.TitleSimple<ArticleRef>(
name = "My Title"
)
val constitution = ConstitutionSimple<CitizenWithUserI, TitleSimple<ArticleRef>>(
id = id ?: params?.get("id")?.toUUID() ?: UUID.randomUUID(),
title = "hello",
titles = mutableListOf(title1),
anonymous = false,
createdBy = createdBy
)
get<ConstitutionRepository>().upsert(constitution)
}
private fun commentConstitution(
constitutionId: String,
firstName: String,
lastName: String,
extraData: DataTable? = null
) {
val params = extraData?.asMap<String, String>(String::class.java, String::class.java)
val constitution =
get<ConstitutionRepository>().findById(UUID.fromString(constitutionId)) ?: error("Constitution not exist")
val citizen = get<CitizenRepository>().findByUsername(
("$firstName-$lastName".toLowerCase()).toLowerCase().replace(' ', '-')
) ?: error("Citizen not exist")
val comment: CommentForUpdate<ConstitutionRef, Citizen> = CommentForUpdate(
id = params?.get("id")?.let { UUID.fromString(it) } ?: UUID.randomUUID(),
createdBy = citizen,
target = constitution,
content = params?.get("content") ?: "hello"
)
get<CommentConstitutionRepository>().comment(comment)
}
}

View File

@@ -1,29 +0,0 @@
package steps
import fr.dcproject.common.utils.toUUID
import fr.dcproject.component.article.ArticleRef
import fr.dcproject.component.citizen.CitizenRepository
import fr.dcproject.component.constitution.ConstitutionRef
import fr.dcproject.component.follow.FollowForUpdate
import io.cucumber.java8.En
import org.koin.test.KoinTest
import org.koin.test.get
import fr.dcproject.component.follow.FollowArticleRepository as FollowArticleRepository
import fr.dcproject.component.follow.FollowConstitutionRepository as FollowConstitutionRepository
class FollowSteps : En, KoinTest {
init {
Given("I have follow of {word} {word} on article {string}") { firstName: String, lastName: String, articleId: String ->
val username = "$firstName-$lastName".toLowerCase()
val citizen = get<CitizenRepository>().findByUsername(username) ?: error("Citizen not exist")
val follow = FollowForUpdate(createdBy = citizen, target = ArticleRef(articleId.toUUID()))
get<FollowArticleRepository>().follow(follow)
}
Given("I have follow of {word} {word} on constitution {string}") { firstName: String, lastName: String, constitutionId: String ->
val username = "$firstName-$lastName".toLowerCase()
val citizen = get<CitizenRepository>().findByUsername(username) ?: error("Citizen not exist")
val follow = FollowForUpdate(createdBy = citizen, target = ConstitutionRef(constitutionId.toUUID()))
get<FollowConstitutionRepository>().follow(follow)
}
}
}

View File

@@ -1,26 +0,0 @@
package steps
import com.auth0.jwt.JWT
import fr.dcproject.component.auth.jwt.JwtConfig
import fr.dcproject.component.citizen.CitizenRepository
import io.cucumber.java8.En
import io.ktor.http.HttpHeaders
import org.koin.test.KoinTest
import org.koin.test.get
class KtorServerAuthSteps : En, KoinTest {
init {
Given("I am authenticated as {word} {word}") { firstName: String, lastName: String ->
val username = "$firstName-$lastName".toLowerCase()
val citizen = get<CitizenRepository>().findByUsername(username) ?: error("Cititzen not exist with username $username")
val jwtAsString: String = JWT.create()
.withIssuer("dc-project.fr")
.withClaim("id", citizen.user.id.toString())
.sign(JwtConfig.algorithm)
KtorServerContext.defaultServer.addPreRequestSetup {
addHeader(HttpHeaders.Authorization, "Bearer $jwtAsString")
}
}
}
}

View File

@@ -1,55 +0,0 @@
package steps
import io.ktor.application.Application
import io.ktor.server.engine.stop
import io.ktor.server.testing.TestApplicationCall
import io.ktor.server.testing.TestApplicationEngine
import io.ktor.server.testing.TestApplicationRequest
import io.ktor.server.testing.createTestEnvironment
import java.util.concurrent.TimeUnit
import kotlin.test.fail
class KtorServerContext(useByDefault: Boolean = true, val module: Application.() -> Unit) {
init { if (useByDefault) setDefault() }
companion object {
lateinit var defaultServer: KtorServerContext
}
private val engine = TestApplicationEngine(createTestEnvironment())
private data class RequestSetup(val setup: TestApplicationRequest.() -> Unit, val keepSetup: Boolean = true)
private val preRequestSetup = mutableListOf<RequestSetup>()
var call: TestApplicationCall? = null
fun addPreRequestSetup(keepSetup: Boolean = true, hook: TestApplicationRequest.() -> Unit) {
preRequestSetup.add(RequestSetup(hook, keepSetup))
}
fun handleRequest(setup: TestApplicationRequest.() -> Unit) =
try {
call = engine.handleRequest {
preRequestSetup.forEach { it.setup(this) }
setup(this)
}
} catch (e: Throwable) {
fail("Request fail, $e")
} finally {
preRequestSetup.removeAll { !it.keepSetup }
}
fun setDefault() {
defaultServer = this
}
fun start() {
engine.start()
module(engine.application)
}
fun stop() {
engine.stop(0L, 0L, TimeUnit.MILLISECONDS)
}
}

View File

@@ -1,69 +0,0 @@
package steps
import com.jayway.jsonpath.JsonPath
import io.cucumber.datatable.DataTable
import io.cucumber.java8.En
import io.ktor.http.ContentType
import io.ktor.http.HttpHeaders
import io.ktor.http.HttpMethod
import io.ktor.http.HttpStatusCode
import io.ktor.server.testing.setBody
import io.ktor.util.KtorExperimentalAPI
import kotlin.test.assertEquals
import kotlin.test.assertNotEquals
@KtorExperimentalAPI
class KtorServerRequestSteps : En {
init {
Given("Next request as headers:") { dataTable: DataTable ->
KtorServerContext.defaultServer.addPreRequestSetup(false) {
dataTable.asMap<String, String>(String::class.java, String::class.java).forEach { key, value ->
this.addHeader(key, value)
}
}
}
Given("I send a {word} request to {string} with body:") { method: String, uri: String, body: String ->
KtorServerContext.defaultServer.handleRequest {
this.method = HttpMethod.parse(method)
this.uri = uri
this.addHeader(HttpHeaders.ContentType, ContentType.Application.Json.toString())
setBody(body)
}
}
Given("I send a {word} request to {string}") { method: String, uri: String ->
KtorServerContext.defaultServer.handleRequest {
this.method = HttpMethod.parse(method.toUpperCase())
this.uri = uri
}
}
Then("the response status code should be {int}") { statusCode: Int ->
assertEquals(
HttpStatusCode.fromValue(statusCode),
KtorServerContext.defaultServer.call?.response?.status(),
KtorServerContext.defaultServer.call?.response?.content
)
}
Then("the response should contain object:") { expected: DataTable ->
expected.asMap<String, String>(String::class.java, String::class.java).forEach { (key, valueExpected) ->
assertEquals(valueExpected, JsonPath.read<Any>(response, key)?.toString() ?: throw AssertionError("\"$key\" element not found on json response"))
}
}
Then("the response should not contain object:") { expected: DataTable ->
expected.asMap<String, String>(String::class.java, String::class.java).forEach { (key, valueExpected) ->
assertNotEquals(valueExpected, JsonPath.read<Any>(response, key)?.toString() ?: throw AssertionError("\"$key\" element not found on json response"))
}
}
Then("print last response") {
print(KtorServerContext.defaultServer.call?.response?.content)
}
}
private val response: String?
get() = KtorServerContext.defaultServer.call?.response?.content
}

View File

@@ -1,66 +0,0 @@
package steps
import io.cucumber.datatable.DataTable
import io.cucumber.java8.En
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonArray
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.JsonPrimitive
import kotlinx.serialization.json.jsonArray
import kotlinx.serialization.json.jsonObject
import kotlin.test.assertEquals
import kotlin.test.assertTrue
import kotlin.test.fail
class KtorServerRestSteps : En {
init {
Then("the JSON should contain:") { dataTable: DataTable ->
dataTable.asMap<String, String>(String::class.java, String::class.java).forEach { (key, value) ->
val jsonPrimitive = findJsonElement(key) as? JsonPrimitive ?: fail("\"$key\" element isn't json primitive")
assertEquals(jsonPrimitive.content, value)
}
}
Then("the JSON element {word} should have {int} item(s)") { node: String, count: Int ->
val jsonArray = findJsonElement(node) as? JsonArray ?: fail("\"$node\" element isn't json array")
assertEquals(count, jsonArray.size)
}
Then("the JSON should have {int} item(s)") { count: Int ->
val jsonArray = responseJsonElement as? JsonArray ?: fail("The json response isn't array")
assertEquals(count, jsonArray.size)
}
Then("the Response should be:") { body: String ->
assertEquals(body, response)
}
Then("the Response should contain:") { body: String ->
assertTrue(response.contains(body))
}
}
private fun findJsonElement(path: String): JsonElement {
var jsonElement: JsonElement = responseJsonElement
path
.split("].", "]", "[", ".")
.filter { it.trim().isNotBlank() }
.map { it.trim() }
.forEach {
jsonElement = if (jsonElement is JsonArray) {
jsonElement.jsonArray[it.toInt()]
} else {
jsonElement.jsonObject[it]
} ?: throw AssertionError("\"$path\" element not found on json response")
}
return jsonElement
}
private val responseJsonElement: JsonElement
get() = Json.parseToJsonElement(KtorServerContext.defaultServer.call?.response?.content ?: fail("The response isn't valid JSON"))
private val response: String
get() = KtorServerContext.defaultServer.call?.response?.content ?: fail("The response isn't valid")
}

View File

@@ -1,82 +0,0 @@
package steps
import fr.dcproject.common.utils.toUUID
import fr.dcproject.component.article.ArticleRef
import fr.dcproject.component.article.ArticleRepository
import fr.dcproject.component.citizen.CitizenRepository
import fr.dcproject.component.opinion.OpinionChoiceRepository
import fr.dcproject.component.opinion.entity.OpinionChoice
import fr.dcproject.component.opinion.entity.OpinionForUpdate
import io.cucumber.datatable.DataTable
import io.cucumber.java8.En
import org.koin.test.KoinTest
import org.koin.test.get
import java.util.UUID
import fr.dcproject.component.opinion.OpinionRepositoryArticle as OpinionRepository
class OpinionSteps : En, KoinTest {
init {
Given("I have an opinion choice {string}") { name: String ->
val opinionChoice = OpinionChoice(
name = name,
target = listOf()
)
get<OpinionRepository>().upsertOpinionChoice(opinionChoice)
}
Given("I have an opinion choice {string} with ID {string}") { name: String, id: String ->
val opinionChoice = OpinionChoice(
id = id.toUUID(),
name = name,
target = listOf()
)
get<OpinionRepository>().upsertOpinionChoice(opinionChoice)
}
Given("I have an opinion {string} on article {string} created by {word} {word}") { opinionChoiceName: String, articleId: String, firstName: String, lastName: String ->
createOpinion(opinionChoiceName, articleId, firstName, lastName)
}
Given("I have an opinion {string} on article {string} created by {word} {word} with ID {string}") { opinionChoiceName: String, articleId: String, firstName: String, lastName: String, id: String ->
createOpinion(opinionChoiceName, articleId, firstName, lastName, id)
}
Given("I have an opinion") { extraInfo: DataTable ->
createOpinionOnArticle(extraInfo)
}
}
private fun createOpinion(
opinionChoiceName: String,
articleId: String,
firstName: String,
lastName: String,
id: String? = null
) {
val opinion = OpinionForUpdate(
id = id?.toUUID() ?: UUID.randomUUID(),
choice = get<OpinionChoiceRepository>().findOpinionsChoiceByName(opinionChoiceName)
?: error("Opinion Choice not exist"),
target = ArticleRef(articleId.toUUID()),
createdBy = get<CitizenRepository>().findByUsername("$firstName-$lastName".toLowerCase().replace(' ', '-'))
?: error("Citizen not exist")
)
get<OpinionRepository>().addOpinion(opinion)
}
private fun createOpinionOnArticle(extraInfo: DataTable? = null) {
val params = extraInfo?.asMap<String, String>(String::class.java, String::class.java)
val username = params?.get("createdBy")?.toLowerCase()?.replace(' ', '-')
?: error("You must provide the 'createdBy' parameter")
val opinion = OpinionForUpdate(
choice = params["opinion"]?.let {
get<OpinionChoiceRepository>().findOpinionsChoiceByName(it) ?: error("Opinion Choice not exist")
} ?: error("You must provide the 'opinion' parameter"),
target = params["article"]?.let {
get<ArticleRepository>().findById(it.toUUID()) ?: error("Article not exist")
} ?: error("You must provide the 'article' parameter"),
createdBy = get<CitizenRepository>().findByUsername(username) ?: error("Citizen not exist")
)
get<OpinionRepository>().updateOpinions(opinion)
}
}

View File

@@ -1,33 +0,0 @@
package steps
import fr.dcproject.common.utils.toUUID
import fr.dcproject.component.article.ArticleRepository
import fr.dcproject.component.citizen.CitizenRepository
import fr.dcproject.component.vote.entity.VoteForUpdate
import io.cucumber.java8.En
import org.koin.test.KoinTest
import org.koin.test.get
import java.util.UUID
import fr.dcproject.component.vote.VoteArticleRepository as VoteRepository
class VoteSteps : En, KoinTest {
init {
Given("I have an vote {int} on article {string} created by {word} {word}") { note: Int, articleId: String, firstName: String, lastName: String ->
createVote(note, articleId, firstName, lastName)
}
Given("I have an vote {int} on article {string} created by {word} {word} with ID {string}") { note: Int, articleId: String, firstName: String, lastName: String, id: String ->
createVote(note, articleId, firstName, lastName, id)
}
}
private fun createVote(note: Int, articleId: String, firstName: String, lastName: String, id: String? = null) {
val vote = VoteForUpdate(
id = id?.toUUID() ?: UUID.randomUUID(),
note = note,
target = get<ArticleRepository>().findById(articleId.toUUID()) ?: error("Article not exist"),
createdBy = get<CitizenRepository>().findByUsername("$firstName-$lastName".toLowerCase().replace(' ', '-')) ?: error("Citizen not exist")
)
get<VoteRepository>().vote(vote)
}
}

View File

@@ -1,76 +0,0 @@
package steps
import fr.dcproject.common.utils.toUUID
import fr.dcproject.component.auth.UserForCreate
import fr.dcproject.component.citizen.CitizenForCreate
import fr.dcproject.component.citizen.CitizenI
import fr.dcproject.component.citizen.CitizenRef
import fr.dcproject.component.citizen.CitizenRepository
import fr.dcproject.component.workgroup.Workgroup
import fr.dcproject.component.workgroup.WorkgroupRef
import fr.dcproject.component.workgroup.WorkgroupRepository
import fr.dcproject.component.workgroup.WorkgroupWithMembersI.Member
import io.cucumber.datatable.DataTable
import io.cucumber.java8.En
import org.joda.time.DateTime
import org.junit.Assert
import org.koin.test.KoinTest
import org.koin.test.get
import java.util.UUID
class WorkgroupSteps : En, KoinTest {
init {
When("I have members in workgroup {string}:") { workgroupId: String, members: DataTable ->
val membersRefs = members.asList()
.map {
Member(
citizen = CitizenRef(it.toUUID()),
roles = listOf(Member.Role.MASTER)
)
}
get<WorkgroupRepository>().addMembers(WorkgroupRef(workgroupId.toUUID()), membersRefs)
}
When("I have workgroup:") { body: DataTable ->
val data = body.asMap<String, String>(String::class.java, String::class.java)
val creator = data["created_by"]?.let {
get<CitizenRepository>().findByUsername(it.toLowerCase().replace(' ', '-'))
} ?: run {
val username = "paul-langevin".toLowerCase() + UUID.randomUUID()
val user = UserForCreate(
username = username,
password = "azerty",
)
CitizenForCreate(
name = CitizenI.Name("Paul", "Langevin"),
email = "$username@dc-project.fr",
birthday = DateTime.now(),
user = user
).let {
get<CitizenRepository>().insertWithUser(it) ?: error("Unable to create User")
}
}
val workgroup = Workgroup(
id = UUID.fromString(data["id"] ?: UUID.randomUUID().toString()),
name = data["name"] ?: "Les Incoruptible",
description = data["description"] ?: "La vie est notre jeux",
createdBy = creator,
anonymous = (data["anonymous"] ?: false) == true,
members = listOf(Member(creator, listOf(Member.Role.MASTER)))
)
get<WorkgroupRepository>().upsert(workgroup)
}
Then("The workgroup {string} exists") { id: String ->
Assert.assertNotNull(get<WorkgroupRepository>().findById(id.toUUID()))
}
Then("The workgroup {string} not exists") { id: String ->
Assert.assertNull(get<WorkgroupRepository>().findById(id.toUUID()))
}
}
}

View File

@@ -1 +0,0 @@
cucumber.publish.quiet=true

View File

@@ -1,55 +0,0 @@
@article
@disable
Feature: articles routes
Scenario: The route for get articles must response a 200
Given I have 3 article
When I send a GET request to "/articles"
Then the response status code should be 200
Scenario: Can get articles filtered by workgroup
Given I have 3 article
And I have workgroup:
| id | 2bccd5a7-9082-4b31-88f8-e25d70b22b12 |
| name | Les papy |
And I have article created by workgroup ID "2bccd5a7-9082-4b31-88f8-e25d70b22b12"
When I send a GET request to "/articles?workgroup=2bccd5a7-9082-4b31-88f8-e25d70b22b12"
Then the response status code should be 200
And the JSON should contain:
| total | 1 |
| result[0]workgroup.name | Les papy |
Scenario: Can get versions of article by the id
Given I have article
| id | 13e6091c-8fed-4600-b079-a97a6b7a9800 |
When I send a GET request to "/articles/13e6091c-8fed-4600-b079-a97a6b7a9800/versions"
Then the response status code should be 200
Scenario: The route for get one article must response a 200 and return article
Given I have article
| id | 65cda9f3-8991-4420-8d41-1da9da72c9bb |
When I send a GET request to "/articles/65cda9f3-8991-4420-8d41-1da9da72c9bb"
Then the response status code should be 200
And the response should contain object:
| id | 65cda9f3-8991-4420-8d41-1da9da72c9bb |
Scenario: The route for create article must response a 200 and return object
Given I have citizen John Doe
And I am authenticated as John Doe
When I send a POST request to "/articles" with body:
"""
{
"version_id": "09c418b6-63ba-448b-b38b-502b41cd500e",
"title": "title2",
"anonymous": false,
"content": "content2",
"description": "description2",
"tags": [
"green"
]
}
"""
Then the response status code should be 200
And the response should contain object:
| version_id | 09c418b6-63ba-448b-b38b-502b41cd500e |
| title | title2 |

View File

@@ -1,52 +0,0 @@
@auth
@disable
Feature: Auth routes
Scenario: I can resiter
When I send a POST request to "/register" with body:
"""
{
"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 status code should be 200
And the Response should contain:
"""
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.
"""
Scenario: I cannot create user if no username was sent
When I send a POST request to "/register" with body:
"""
{
"name": {"first_name":"George2", "last_name":"MICHEL2"},
"birthday": "2001-01-01",
"user":{
"username": "",
"password": ""
}
}
"""
Then the response status code should be 400
Scenario: I can login with username and password
The route for create citizen must response a 200 and return object
Given I have citizen Niels Bohr
When I send a POST request to "/login" with body:
"""
{
"username": "niels-bohr",
"password": "azerty"
}
"""
Then the response status code should be 200
And the Response should contain:
"""
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.
"""

View File

@@ -1,66 +0,0 @@
@citizen
@disable
Feature: citizens routes
Scenario: I can get Citizens informations
Given I have citizen Jean Perrin with ID "5267a5c6-af42-4a02-aa2b-6b71d2e43973"
And I am authenticated as Jean Perrin
When I send a GET request to "/citizens"
Then the response status code should be 200
Scenario: I can get specific Citizen informations
Given I have citizen Linus Pauling with ID "47a05c0f-7329-46c3-a7d0-325db37e9114"
Given I am authenticated as Linus Pauling
When I send a GET request to "/citizens/47a05c0f-7329-46c3-a7d0-325db37e9114"
Then the response status code should be 200
And the response should contain object:
| id | 47a05c0f-7329-46c3-a7d0-325db37e9114 |
Scenario: I can get my citizen informations when I was connected
Given I have citizen Henri Becquerel with ID "47356809-c8ef-4649-8b99-1c5cb9886d38"
And I am authenticated as Henri Becquerel
When I send a GET request to "/citizens/current"
Then the response status code should be 200
And the response should contain object:
| id | 47356809-c8ef-4649-8b99-1c5cb9886d38 |
@online
Scenario: I can be connect with Passwordless auth
Given I have citizen
| id | c606110c-ff0e-4d09-a79e-74632d7bf7bd |
| email | fabrice.lecomte.be@gmail.com |
| firstName | Leonhard |
| lastName | Euler |
When I send a POST request to "/auth/passwordless" with body:
"""
{
"url": "https://dc-project.fr/password/reset",
"email": "fabrice.lecomte.be@gmail.com"
}
"""
Then the response status code should be 204
Scenario: Can be change my password
Given I have citizen Georges Charpak with ID "0c966522-4071-43e5-a3ca-cfff2557f2cf"
And I am authenticated as Georges Charpak
When I send a PUT request to "/citizens/0c966522-4071-43e5-a3ca-cfff2557f2cf/password/change" with body:
"""
{
"old_password": "azerty",
"new_password": "qwerty"
}
"""
Then the response status code should be 201
Scenario: If a send bad request when a change password, that return a 400 Bad request
Given I have citizen Louis Breguet with ID "6cf2a19d-d15d-4ee5-b2a9-907afd26b525"
And I am authenticated as Louis Breguet
When I send a PUT request to "/citizens/6cf2a19d-d15d-4ee5-b2a9-907afd26b525/password/change" with body:
"""
{
"plup": "azerty",
"gloup": "qwerty"
}
"""
Then the response status code should be 400

View File

@@ -1,12 +0,0 @@
@comment
@disable
Feature: comment
Scenario: Can comment childrens
Given I have citizen John Dalton
And I am authenticated as John Dalton
And I have article
| id | 4c948e8f-eada-4e10-8d7d-7192affe1313 |
And I have comment created by John Dalton on article "4c948e8f-eada-4e10-8d7d-7192affe1313"
When I send a GET request to "/comments/4c948e8f-eada-4e10-8d7d-7192affe1313/children"
Then the response status code should be 200

View File

@@ -1,81 +0,0 @@
@comment
@disable
Feature: comment Article
Scenario: Can comment an article
Given I have citizen Michael Faraday
And I am authenticated as Michael Faraday
And I have article
| id | aa16c635-28da-46f0-9a89-934eef88c7ca |
When I send a POST request to "/articles/aa16c635-28da-46f0-9a89-934eef88c7ca/comments" with body:
"""
{
"content": "Hello mister"
}
"""
Then the response status code should be 201
# TODO add more comment on article
Scenario: Can get all comment on article
Given I have citizen Enrico Fermi
And I am authenticated as Enrico Fermi
And I have article
| id | 6166c078-ca97-4366-b0aa-2a5cd558c78a |
And I have comment created by Enrico Fermi on article "6166c078-ca97-4366-b0aa-2a5cd558c78a"
When I send a GET request to "/articles/6166c078-ca97-4366-b0aa-2a5cd558c78a/comments"
Then the response status code should be 200
# TODO add votes
Scenario: Can get all comment on article sorted by votes
Given I have citizen Pierre Curie
And I am authenticated as Pierre Curie
And I have article
| id | 5e209f63-57ce-43ca-922a-273b0d62f567 |
And I have comment created by Pierre Curie on article "5e209f63-57ce-43ca-922a-273b0d62f567"
When I send a GET request to "/articles/5e209f63-57ce-43ca-922a-273b0d62f567/comments?sort=votes"
Then the response status code should be 200
And the response should contain object:
| $.result[0].votes.up | 0 |
Scenario: Can get comments on articles of the current citizen
Given I have citizen Erwin Schrodinger with ID "292a20cc-4a60-489e-9866-a95d38ffaf47"
And I have article
| id | 17df7fb9-b388-4e20-ab19-29c29972da01 |
| createdBy | Erwin Schrodinger |
And I have comment created by Erwin Schrodinger on article "17df7fb9-b388-4e20-ab19-29c29972da01"
When I send a GET request to "/citizens/292a20cc-4a60-489e-9866-a95d38ffaf47/comments/articles"
Then the response status code should be 200
And the response should contain object:
| current_page | 1 |
| limit | 50 |
And the Response should contain:
"""
292a20cc-4a60-489e-9866-a95d38ffaf47
"""
Scenario: Can edit a comment
Given I have citizen Hubert Reeves
And I have article
| id | bb05e4a3-55a1-4088-85e7-8d8c23be29b1 |
And I am authenticated as Hubert Reeves
And I have comment created by Hubert Reeves on article "bb05e4a3-55a1-4088-85e7-8d8c23be29b1":
| id | fd30d20f-656c-42c6-8955-f61c04537464 |
When I send a PUT request to "/comments/fd30d20f-656c-42c6-8955-f61c04537464" with body:
"""
Hello boy
"""
Then the response status code should be 200
And the JSON should contain:
| content | Hello boy |
Scenario: Can get comment by its ID
Given I have citizen Alfred Kastler
And I have article
| id | 3897465b-19d2-43a0-86ea-1e29dbb11ec9 |
And I have comment created by Alfred Kastler on article "3897465b-19d2-43a0-86ea-1e29dbb11ec9":
| id | edd296a8-fc7a-4717-a2bb-9f035ceca3c2 |
| content | Hello boy |
When I send a GET request to "/comments/edd296a8-fc7a-4717-a2bb-9f035ceca3c2"
Then the response status code should be 200
And the JSON should contain:
| content | Hello boy |

View File

@@ -1,32 +0,0 @@
@comment
@disable
Feature: comment Constitution
Scenario: Can comment an constitution
Given I have citizen Nicolas Copernic
And I am authenticated as Nicolas Copernic
And I have constitution
| id | 1707c287-a472-4a62-89f2-9e85030e915c |
When I send a POST request to "/constitutions/1707c287-a472-4a62-89f2-9e85030e915c/comments" with body:
"""
{
"content": "Hello mister"
}
"""
Then the response status code should be 201
Scenario: Can get comments on constitutions of the current citizen
Given I have citizen Charles Darwin with ID "46e0bda9-ca6a-4c65-a58b-7e7267a0bbc5"
And I have constitution
| id | 34ddd50a-da00-4a90-a869-08baa2a121be |
| createdBy | Charles Darwin |
And I have comment created by Charles Darwin on constitution "34ddd50a-da00-4a90-a869-08baa2a121be"
When I send a GET request to "/citizens/46e0bda9-ca6a-4c65-a58b-7e7267a0bbc5/comments/constitutions"
Then the response status code should be 200
And the response should contain object:
| current_page | 1 |
| limit | 50 |
And the Response should contain:
"""
34ddd50a-da00-4a90-a869-08baa2a121be
"""

View File

@@ -1,37 +0,0 @@
@constitution
@disable
Feature: constitution
Scenario: The route for get constitutions must response a 200
Given I have 3 constitution
When I send a GET request to "/constitutions"
Then the response status code should be 200
Scenario: The route for get one constitution must response a 200 and return constitution
Given I have constitution with ID "0321c8d1-4ce3-4763-b5f4-a92611d280b4"
When I send a GET request to "/constitutions/0321c8d1-4ce3-4763-b5f4-a92611d280b4"
Then the response status code should be 200
And the response should contain object:
| id | 0321c8d1-4ce3-4763-b5f4-a92611d280b4 |
Scenario: The route for create constitution must response a 200 and return object
Given I have citizen Henri Poincaré
And I am authenticated as Henri Poincaré
When I send a POST request to "/constitutions" with body:
"""
{
"version_id":"15814bb6-8d90-4c6a-a456-c3939a8ec75e",
"title":"Hello world!",
"anonymous":true,
"titles":[
{
"name":"plop",
"rank":0
}
]
}
"""
Then the response status code should be 200
And the response should contain object:
| version_id | 15814bb6-8d90-4c6a-a456-c3939a8ec75e |
| title | Hello world! |

View File

@@ -1,43 +0,0 @@
@follow
@disable
Feature: follow Article
# Article
Scenario: The route for follow article must response a 201
Given I have citizen Louis Pasteur
And I am authenticated as Louis Pasteur
And I have article
| id | 04754b7b-edef-4adc-af81-75e3aadeebea |
When I send a POST request to "/articles/04754b7b-edef-4adc-af81-75e3aadeebea/follows"
Then the response status code should be 201
Scenario: The route for get follows of articles must response a 200 and return objects
Given I have citizen Johannes Kepler with ID "e4592d53-3660-4264-8353-ebdbf5d9c41c"
And I am authenticated as Johannes Kepler
And I have article
| id | d743619a-1f6b-4d20-a2d6-8e81f0e6a4c8 |
And I have follow of Johannes Kepler on article "d743619a-1f6b-4d20-a2d6-8e81f0e6a4c8"
When I send a GET request to "/citizens/e4592d53-3660-4264-8353-ebdbf5d9c41c/follows/articles"
Then the response status code should be 200
And the response should contain object:
| current_page | 1 |
| limit | 50 |
Scenario: The route for unfollow article must response a 204
Given I have citizen Thomas Edison
And I am authenticated as Thomas Edison
And I have article
| id | aad3aa9d-95fd-4919-9e84-46255f620e31 |
And I have follow of Thomas Edison on article "aad3aa9d-95fd-4919-9e84-46255f620e31"
When I send a DELETE request to "/articles/aad3aa9d-95fd-4919-9e84-46255f620e31/follows"
Then the response status code should be 204
Scenario: I can know if I follow an article
Given I have article with ID "3ee4e6d0-f312-4940-872d-1f578c8d824c"
And I have citizen Marie Curie
And I am authenticated as Marie Curie
And I have follow of Marie Curie on article "3ee4e6d0-f312-4940-872d-1f578c8d824c"
When I send a GET request to "/articles/3ee4e6d0-f312-4940-872d-1f578c8d824c/follows"
Then the response status code should be 200
And the JSON should contain:
| target.id | 3ee4e6d0-f312-4940-872d-1f578c8d824c |

View File

@@ -1,43 +0,0 @@
@follow
@disable
Feature: follow Constitution
# Constitution
Scenario: The route for follow constitution must response a 201 and return
Given I have citizen Dmitri Mendeleïev
And I am authenticated as Dmitri Mendeleïev
And I have constitution
| id | f6553f5e-0cf5-476a-b84e-15e52ec9d8f9 |
When I send a POST request to "/constitutions/f6553f5e-0cf5-476a-b84e-15e52ec9d8f9/follows"
Then the response status code should be 201
Scenario: The route for get follows of constitutions must response a 200 and return objects
Given I have citizen André-Marie Ampère with ID "877b45b0-302d-487d-8944-6d03ccdbd0f8"
And I am authenticated as André-Marie Ampère
And I have constitution
| id | 7f642078-8e74-47fc-9712-0c37531674a0 |
And I have follow of André-Marie Ampère on constitution "7f642078-8e74-47fc-9712-0c37531674a0"
When I send a GET request to "/citizens/877b45b0-302d-487d-8944-6d03ccdbd0f8/follows/constitutions"
Then the response status code should be 200
And the response should contain object:
| current_page | 1 |
| limit | 50 |
Scenario: The route for unfollow constitution must response a 204
Given I have citizen Claude Ptolémée
And I am authenticated as Claude Ptolémée
And I have constitution
| id | 4ea03776-a28c-4202-9b90-db1b942946c1 |
And I have follow of Claude Ptolémée on constitution "4ea03776-a28c-4202-9b90-db1b942946c1"
When I send a DELETE request to "/constitutions/4ea03776-a28c-4202-9b90-db1b942946c1/follows"
Then the response status code should be 204
Scenario: I can know if I follow an constitution
Given I have constitution with ID "5141e781-ebcd-4de0-8c2b-7d23d4cd58b5"
And I have citizen Denis Papin
And I am authenticated as Denis Papin
And I have follow of Denis Papin on constitution "5141e781-ebcd-4de0-8c2b-7d23d4cd58b5"
When I send a GET request to "/constitutions/5141e781-ebcd-4de0-8c2b-7d23d4cd58b5/follows"
Then the response status code should be 200
And the JSON should contain:
| target.id | 5141e781-ebcd-4de0-8c2b-7d23d4cd58b5 |

View File

@@ -1,75 +0,0 @@
@opinion
@disable
Feature: Opinion
Scenario: Can get all opinion choices
Given I have an opinion choice "Opinion1"
And I have an opinion choice "Opinion2"
When I send a GET request to "/opinions"
Then the response status code should be 200
And the JSON should contain:
| [0]name | Opinion1 |
| [1]name | Opinion2 |
Scenario: Can get one opinion Choices
Given I have an opinion choice "Opinion3" with ID "347ec243-0e76-4ab5-9884-7bd503cf5ab5"
When I send a GET request to "/opinions/347ec243-0e76-4ab5-9884-7bd503cf5ab5"
Then the response status code should be 200
And the JSON should contain:
| name | Opinion3 |
Scenario: Can create opinion on article
Given I have citizen Isaac Newton with ID "2f414045-95d9-42ca-a3a9-8cdde52ad253"
And I am authenticated as Isaac Newton
And I have article
| id | 9226c1a3-8091-c3fa-7d0d-c2e98c9bee7b |
| createdBy | Isaac Newton |
And I have an opinion choice "Opinion4" with ID "0f4f1721-3136-44f1-9f31-1459f3317b15"
When I send a PUT request to "/articles/9226c1a3-8091-c3fa-7d0d-c2e98c9bee7b/opinions" with body:
"""
{
"ids": [
"0f4f1721-3136-44f1-9f31-1459f3317b15"
]
}
"""
Then the response status code should be 201
Scenario: Can I get all opinions of citizen filtered by target ids
Given I have article with ID "4eb8a2c6-ba63-4c1e-919f-72017132a54e"
And I have citizen Albert Jacquard with ID "c6392fc4-56f5-461b-8015-953a4da3029f"
And I am authenticated as Albert Jacquard
And I have an opinion choice "Opinion5" with ID "74d6e105-9aa6-4589-8776-82ce260bb6f4"
And I have an opinion "Opinion5" on article "4eb8a2c6-ba63-4c1e-919f-72017132a54e" created by Albert Jacquard with ID "994660e7-e9f4-4ae9-9290-b34d78663c7a"
When I send a GET request to "/citizens/c6392fc4-56f5-461b-8015-953a4da3029f/opinions?id=4eb8a2c6-ba63-4c1e-919f-72017132a54e"
Then the response status code should be 200
And the JSON should contain:
| [0].name | Opinion5 |
Scenario: Can recieve opinion aggregation with article
Given I have an opinion choice "Opinion6"
And I have an opinion choice "Opinion7"
And I have an opinion choice "Opinion8"
And I have citizen James Watt
And I have citizen Paul Langevin
And I have article with ID "bda8940a-6792-4f2b-936a-ba5c805c8487"
And I have an opinion "Opinion6" on article "bda8940a-6792-4f2b-936a-ba5c805c8487" created by James Watt
And I have an opinion "Opinion7" on article "bda8940a-6792-4f2b-936a-ba5c805c8487" created by James Watt
And I have an opinion "Opinion7" on article "bda8940a-6792-4f2b-936a-ba5c805c8487" created by Paul Langevin
When I send a GET request to "/articles/bda8940a-6792-4f2b-936a-ba5c805c8487"
Then the response status code should be 200
And the JSON should contain:
| opinions.Opinion6 | 1 |
| opinions.Opinion7 | 2 |
Scenario: Can get all opinion of one citizen
Given I have citizen Albert Einstein with ID "c1542096-3431-432d-8e35-9dc071d4c818"
And I am authenticated as Albert Einstein
And I have an opinion choice "Opinion9"
And I have article with ID "8651b530-ac1b-4214-a784-706781371074"
And I have an opinion "Opinion9" on article "8651b530-ac1b-4214-a784-706781371074" created by Albert Einstein
When I send a GET request to "/citizens/c1542096-3431-432d-8e35-9dc071d4c818/opinions/articles"
Then the response status code should be 200
And the JSON element result should have 1 items
And the JSON should contain:
| result[0].name | Opinion9 |

View File

@@ -1,69 +0,0 @@
@vote
@disable
Feature: vote Article
Scenario: Can Vote article
Given I have citizen Thalès Milet
And I am authenticated as Thalès Milet
And I have article with ID "835c5101-ca39-4038-a4e6-da6ee62ca6d5"
When I send a PUT request to "/articles/835c5101-ca39-4038-a4e6-da6ee62ca6d5/vote" with body:
"""
{
"note": 1
}
"""
Then the response status code should be 201
Scenario: Can Vote constitution
Given I have citizen Gregor Mendel
And I am authenticated as Gregor Mendel
And I have constitution with ID "76e79c89-efc1-492d-9e8f-dc9717363a11"
When I send a PUT request to "/constitutions/76e79c89-efc1-492d-9e8f-dc9717363a11/vote" with body:
"""
{
"note": -1
}
"""
Then the response status code should be 201
Scenario: Can get votes of current citizen
Given I have citizen Carl Gauss with ID "c044823d-e778-4256-9016-b1334bf933d3"
And I am authenticated as Carl Gauss
And I have article with ID "7c9286db-470d-448c-aab1-3f0b072213b1"
And I have an vote 1 on article "7c9286db-470d-448c-aab1-3f0b072213b1" created by Carl Gauss
When I send a GET request to "/citizens/c044823d-e778-4256-9016-b1334bf933d3/votes/articles"
Then the response status code should be 200
And the response should contain object:
| current_page | 1 |
| limit | 50 |
| total | 1 |
| result[0].note | 1 |
Scenario: Can get votes of current citizen by target ids
Given I have citizen Rosalind Franklin with ID "ab3269f0-877b-46b2-ae1a-e7e7d1c12132"
And I am authenticated as Rosalind Franklin
And I have article with ID "4d457f53-b937-4622-9542-d5f689d3716b"
And I have an vote 1 on article "4d457f53-b937-4622-9542-d5f689d3716b" created by Rosalind Franklin
And I have article with ID "117ef3e6-a740-4d04-9a4a-a800a5f274b4"
And I have an vote -1 on article "117ef3e6-a740-4d04-9a4a-a800a5f274b4" created by Rosalind Franklin
When I send a GET request to "/citizens/ab3269f0-877b-46b2-ae1a-e7e7d1c12132/votes?id=4d457f53-b937-4622-9542-d5f689d3716b&id=117ef3e6-a740-4d04-9a4a-a800a5f274b4"
Then the response status code should be 200
And the response should contain object:
| [0].note | -1 |
| [1].note | 1 |
Scenario: Can vote a comment
Given I have citizen Antoine Lavoisier
And I am authenticated as Antoine Lavoisier
And I have article with ID "54428366-e71e-4961-876c-8a13df5e4b41"
And I have comment created by Antoine Lavoisier on article "54428366-e71e-4961-876c-8a13df5e4b41":
| id | e793eccc-456b-4450-a292-46d592229b74 |
When I send a PUT request to "/comments/e793eccc-456b-4450-a292-46d592229b74/vote" with body:
"""
{
"note": -1
}
"""
Then the response status code should be 201
And the response should contain object:
| down | 1 |

View File

@@ -1,147 +0,0 @@
@workgroup
@disable
Feature: Workgroup
Scenario: Can get one workgroup
Given I have citizen Stephen Hawking
And I have citizen Sadi Carnot with ID "be3b0926-8628-4426-804a-75188a6eb315"
And I have citizen Joseph Fourier with ID "d9671eca-abaf-4b67-9230-3ece700c1ddb"
And I am authenticated as Stephen Hawking
And I have workgroup:
| id | ab469134-bf14-4856-b093-ae1aa990f977 |
| name | Les Mousquets |
| created_by | Stephen Hawking |
And I have members in workgroup "ab469134-bf14-4856-b093-ae1aa990f977":
| be3b0926-8628-4426-804a-75188a6eb315 |
| d9671eca-abaf-4b67-9230-3ece700c1ddb |
When I send a GET request to "/workgroups/ab469134-bf14-4856-b093-ae1aa990f977"
Then the response status code should be 200
And the response should contain object:
| $.id | ab469134-bf14-4856-b093-ae1aa990f977 |
| $.name | Les Mousquets |
| $.members[0].citizen.name.first_name | Stephen |
| $.members[1].citizen.name.first_name | Sadi |
Scenario: Can create a workgroup
Given I have citizen Werner Heisenberg
And I am authenticated as Werner Heisenberg
When I send a POST request to "/workgroups" with body:
"""
{
"id":"f496d86d-6654-4068-91ff-90e1dbcc5f38",
"name":"Les Bouffons",
"description":"La vie est belle",
"anonymous":false
}
"""
Then the response status code should be 201
And the JSON should contain:
| id | f496d86d-6654-4068-91ff-90e1dbcc5f38 |
| name | Les Bouffons |
| description | La vie est belle |
| anonymous | false |
Scenario: Can delete a workgroup
Given I have citizen Werner Heisenberg
And I am authenticated as Werner Heisenberg
And I have workgroup:
| id | ab469134-bf14-4856-b093-ae1aa990f977 |
| created_by | Werner Heisenberg |
When I send a DELETE request to "/workgroups/ab469134-bf14-4856-b093-ae1aa990f977"
Then the response status code should be 204
And The workgroup "ab469134-bf14-4856-b093-ae1aa990f977" not exists
Scenario: Can get workgroups list
Given I have citizen Max Planck
And I am authenticated as Max Planck
And I have workgroup:
| id | 3fd8edb6-c4b4-4c94-bc75-ddd9b290d32c |
| name | Les Pissenlits |
When I send a GET request to "/workgroups"
Then the response status code should be 200
And the response should contain object:
| $.result[0]id | 3fd8edb6-c4b4-4c94-bc75-ddd9b290d32c |
Scenario: Can add member to workgroup
Given I have citizen Blaise Pascal
And I have citizen Roger Penrose with ID "6d883fe7-5fc0-4a50-8858-72230673eba4"
And I have citizen Alessandro Volta with ID "b5bac515-45d4-4aeb-9b6d-2627a0bbc419"
And I am authenticated as Blaise Pascal
And I have workgroup:
| id | b0ea1922-3bc6-44e2-aa7c-40158998cfbb |
| name | Les bonobos |
| created_by | Blaise Pascal |
When I send a POST request to "/workgroups/b0ea1922-3bc6-44e2-aa7c-40158998cfbb/members" with body:
"""
[
{
"citizen": {"id":"6d883fe7-5fc0-4a50-8858-72230673eba4"},
"roles": ["MASTER"]
},
{
"citizen": {"id":"b5bac515-45d4-4aeb-9b6d-2627a0bbc419"},
"roles": ["MASTER"]
}
]
"""
Then the response status code should be 201
Scenario: Can remove member to workgroup
Given I have citizen Heinrich Hertz with
| id | 94f92424-c257-4582-907c-98564a8c4ac9 |
And I have citizen William Thomson with ID "87909ba3-2069-431c-9924-219fd8411cf2"
And I have citizen Paul Dirac with ID "1baf48bb-02bc-4d8f-ac86-33335354f5e7"
And I am authenticated as Heinrich Hertz
And I have workgroup:
| id | b6c975df-dd44-4e99-adc1-f605746b0e11 |
| name | Les Tacos |
| created_by | Heinrich Hertz |
And I have members in workgroup "b6c975df-dd44-4e99-adc1-f605746b0e11":
| 87909ba3-2069-431c-9924-219fd8411cf2 |
| 1baf48bb-02bc-4d8f-ac86-33335354f5e7 |
When I send a DELETE request to "/workgroups/b6c975df-dd44-4e99-adc1-f605746b0e11/members" with body:
"""
[
{
"citizen": {"id":"87909ba3-2069-431c-9924-219fd8411cf2"},
"roles": ["MASTER"]
}
]
"""
Then the response status code should be 200
And the JSON should have 2 items
And the response should contain object:
| $.[0]citizen.id | 94f92424-c257-4582-907c-98564a8c4ac9 |
| $.[1]citizen.id | 1baf48bb-02bc-4d8f-ac86-33335354f5e7 |
Scenario: Can update members on workgroup
Given I have citizen Leon Foucault
And I have citizen Sadi Carnot with ID "be3b0926-8628-4426-804a-75188a6eb315"
And I have citizen Joseph Fourier with ID "d9671eca-abaf-4b67-9230-3ece700c1ddb"
And I have citizen Georg Ohm with ID "b49e20c1-8393-45d6-a6a0-3fa5c71cbdc1"
And I am authenticated as Leon Foucault
And I have workgroup:
| id | 784fe6bc-7635-4ae2-b080-3a4743b998bf |
| name | Les Tacos |
| created_by | Leon Foucault |
And I have members in workgroup "784fe6bc-7635-4ae2-b080-3a4743b998bf":
| be3b0926-8628-4426-804a-75188a6eb315 |
| d9671eca-abaf-4b67-9230-3ece700c1ddb |
When I send a PUT request to "/workgroups/784fe6bc-7635-4ae2-b080-3a4743b998bf/members" with body:
"""
[
{
"citizen": {"id":"be3b0926-8628-4426-804a-75188a6eb315"},
"roles": ["MASTER"]
},
{
"citizen": {"id":"b49e20c1-8393-45d6-a6a0-3fa5c71cbdc1"},
"roles": ["MASTER"]
}
]
"""
Then the response status code should be 200
And the JSON should have 2 items
And the response should contain object:
| $.[0]citizen.id | be3b0926-8628-4426-804a-75188a6eb315 |
| $.[1]citizen.id | b49e20c1-8393-45d6-a6a0-3fa5c71cbdc1 |