Merge branch 'refactoring-test'
This commit is contained in:
1
.idea/runConfigurations/All_Tests___Lint.xml
generated
1
.idea/runConfigurations/All_Tests___Lint.xml
generated
@@ -6,6 +6,7 @@
|
||||
<option name="MAIN_CLASS_NAME" value="" />
|
||||
<option name="METHOD_NAME" value="" />
|
||||
<option name="TEST_OBJECT" value="package" />
|
||||
<option name="VM_PARAMETERS" value="-ea -Djdk.attach.allowAttachSelf=true" />
|
||||
<option name="PARAMETERS" value="" />
|
||||
<option name="TEST_SEARCH_SCOPE">
|
||||
<value defaultName="wholeProject" />
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<option name="MAIN_CLASS_NAME" value="" />
|
||||
<option name="METHOD_NAME" value="" />
|
||||
<option name="TEST_OBJECT" value="tags" />
|
||||
<option name="VM_PARAMETERS" value="-ea -Dcucumber.options="--tags ~@online"" />
|
||||
<option name="VM_PARAMETERS" value="-ea -Dcucumber.options="--tags ~@online" -Djdk.attach.allowAttachSelf=true" />
|
||||
<option name="PARAMETERS" value="" />
|
||||
<option name="TEST_SEARCH_SCOPE">
|
||||
<value defaultName="wholeProject" />
|
||||
|
||||
2
.idea/runConfigurations/Article_Tests.xml
generated
2
.idea/runConfigurations/Article_Tests.xml
generated
@@ -1,5 +1,5 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="Article Tests" type="JUnit" factoryName="JUnit" show_console_on_std_err="true">
|
||||
<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 />
|
||||
|
||||
24
.idea/runConfigurations/Auth_Tests.xml
generated
Normal file
24
.idea/runConfigurations/Auth_Tests.xml
generated
Normal file
@@ -0,0 +1,24 @@
|
||||
<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="RunCucumberTest" />
|
||||
<option name="METHOD_NAME" value="" />
|
||||
<option name="TEST_OBJECT" value="class" />
|
||||
<option name="VM_PARAMETERS" value="-ea -Dcucumber.filter.tags="@auth"" />
|
||||
<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>
|
||||
24
.idea/runConfigurations/Citizen_Tests.xml
generated
Normal file
24
.idea/runConfigurations/Citizen_Tests.xml
generated
Normal file
@@ -0,0 +1,24 @@
|
||||
<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="RunCucumberTest" />
|
||||
<option name="METHOD_NAME" value="" />
|
||||
<option name="TEST_OBJECT" value="class" />
|
||||
<option name="VM_PARAMETERS" value="-ea -Dcucumber.filter.tags="@citizen"" />
|
||||
<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>
|
||||
24
.idea/runConfigurations/Comment_Tests.xml
generated
Normal file
24
.idea/runConfigurations/Comment_Tests.xml
generated
Normal file
@@ -0,0 +1,24 @@
|
||||
<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="RunCucumberTest" />
|
||||
<option name="METHOD_NAME" value="" />
|
||||
<option name="TEST_OBJECT" value="class" />
|
||||
<option name="VM_PARAMETERS" value="-ea -Dcucumber.filter.tags="@comment"" />
|
||||
<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>
|
||||
24
.idea/runConfigurations/Constitution_Tests.xml
generated
Normal file
24
.idea/runConfigurations/Constitution_Tests.xml
generated
Normal file
@@ -0,0 +1,24 @@
|
||||
<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="RunCucumberTest" />
|
||||
<option name="METHOD_NAME" value="" />
|
||||
<option name="TEST_OBJECT" value="class" />
|
||||
<option name="VM_PARAMETERS" value="-ea -Dcucumber.filter.tags="@constitution"" />
|
||||
<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>
|
||||
2
.idea/runConfigurations/Cucumber_Tests.xml
generated
2
.idea/runConfigurations/Cucumber_Tests.xml
generated
@@ -2,10 +2,12 @@
|
||||
<configuration default="false" name="Cucumber Tests" type="JUnit" factoryName="JUnit">
|
||||
<output_file path="$PROJECT_DIR$/var/log/test/cucumber.out.log" />
|
||||
<module name="dcproject.test" />
|
||||
<useClassPathOnly />
|
||||
<option name="PACKAGE_NAME" value="" />
|
||||
<option name="MAIN_CLASS_NAME" value="RunCucumberTest" />
|
||||
<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$" />
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="All Tests (offline)" type="JUnit" factoryName="JUnit" show_console_on_std_err="true">
|
||||
<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 />
|
||||
@@ -13,7 +13,7 @@
|
||||
<option name="MAIN_CLASS_NAME" value="RunCucumberTest" />
|
||||
<option name="METHOD_NAME" value="" />
|
||||
<option name="TEST_OBJECT" value="class" />
|
||||
<option name="VM_PARAMETERS" value="-ea -Dcucumber.filter.tags=" not @online" -Dstrict" />
|
||||
<option name="VM_PARAMETERS" value="-ea -Dcucumber.filter.tags=" not @online" -Djdk.attach.allowAttachSelf=true" />
|
||||
<option name="PARAMETERS" value="" />
|
||||
<option name="TEST_SEARCH_SCOPE">
|
||||
<value defaultName="wholeProject" />
|
||||
4
.idea/runConfigurations/Follow_Tests.xml
generated
4
.idea/runConfigurations/Follow_Tests.xml
generated
@@ -1,5 +1,5 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="Follow Tests" type="JUnit" factoryName="JUnit" show_console_on_std_err="true">
|
||||
<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 />
|
||||
@@ -7,7 +7,7 @@
|
||||
<option name="MAIN_CLASS_NAME" value="RunCucumberTest" />
|
||||
<option name="METHOD_NAME" value="" />
|
||||
<option name="TEST_OBJECT" value="class" />
|
||||
<option name="VM_PARAMETERS" value="-ea -Dcucumber.filter.tags="@follow" -Dstrict" />
|
||||
<option name="VM_PARAMETERS" value="-ea -Dcucumber.filter.tags="@follow"" />
|
||||
<option name="PARAMETERS" value="" />
|
||||
<option name="TEST_SEARCH_SCOPE">
|
||||
<value defaultName="wholeProject" />
|
||||
|
||||
2
.idea/runConfigurations/Mark_as__error.xml
generated
2
.idea/runConfigurations/Mark_as__error.xml
generated
@@ -1,5 +1,5 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="Mark as @error" type="JUnit" factoryName="JUnit" show_console_on_std_err="true">
|
||||
<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 />
|
||||
|
||||
4
.idea/runConfigurations/Opinion_Tests.xml
generated
4
.idea/runConfigurations/Opinion_Tests.xml
generated
@@ -1,5 +1,5 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="Opinion Tests" type="JUnit" factoryName="JUnit" show_console_on_std_err="true">
|
||||
<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 />
|
||||
@@ -7,7 +7,7 @@
|
||||
<option name="MAIN_CLASS_NAME" value="RunCucumberTest" />
|
||||
<option name="METHOD_NAME" value="" />
|
||||
<option name="TEST_OBJECT" value="class" />
|
||||
<option name="VM_PARAMETERS" value="-ea -Dcucumber.filter.tags="@opinion" -Dstrict" />
|
||||
<option name="VM_PARAMETERS" value="-ea -Dcucumber.filter.tags="@opinion"" />
|
||||
<option name="PARAMETERS" value="" />
|
||||
<option name="TEST_SEARCH_SCOPE">
|
||||
<value defaultName="wholeProject" />
|
||||
|
||||
3
.idea/runConfigurations/Test_All_SQL.xml
generated
3
.idea/runConfigurations/Test_All_SQL.xml
generated
@@ -1,5 +1,5 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="Test All SQL" type="DatabaseScript" folderName="SQL TEST" editBeforeRun="true">
|
||||
<configuration default="false" name="Test All SQL" type="DatabaseScript" folderName="SQL TEST">
|
||||
<script-file value="$PROJECT_DIR$/src/main/resources/sql/functions/article/find_article_by_id.sql" />
|
||||
<script-file value="$PROJECT_DIR$/src/main/resources/sql/functions/article/find_articles.sql" />
|
||||
<script-file value="$PROJECT_DIR$/src/main/resources/sql/functions/article/find_articles_versions_by_id.sql" />
|
||||
@@ -53,6 +53,7 @@
|
||||
<script-file value="$PROJECT_DIR$/src/main/resources/sql/functions/opinion/find_opinion_choices.sql" />
|
||||
<script-file value="$PROJECT_DIR$/src/main/resources/sql/functions/opinion/find_opinion_by_id.sql" />
|
||||
<script-file value="$PROJECT_DIR$/src/main/resources/sql/functions/opinion/upsert_opinion.sql" />
|
||||
<script-file value="$PROJECT_DIR$/src/main/resources/sql/functions/opinion/upsert_opinion_choice.sql" />
|
||||
<script-file value="$PROJECT_DIR$/src/main/resources/sql/functions/workgroup/find_workgroup_by_id.sql" />
|
||||
<script-file value="$PROJECT_DIR$/src/main/resources/sql/functions/workgroup/find_workgroups.sql" />
|
||||
<script-file value="$PROJECT_DIR$/src/main/resources/sql/functions/workgroup/upsert_workgroup.sql" />
|
||||
|
||||
1
.idea/runConfigurations/Test_Opinions.xml
generated
1
.idea/runConfigurations/Test_Opinions.xml
generated
@@ -9,6 +9,7 @@
|
||||
<script-file value="$PROJECT_DIR$/src/main/resources/sql/functions/opinion/find_opinion_choices.sql" />
|
||||
<script-file value="$PROJECT_DIR$/src/main/resources/sql/functions/opinion/upsert_opinion.sql" />
|
||||
<script-file value="$PROJECT_DIR$/src/main/resources/sql/functions/opinion/find_opinion_by_opinion.sql" />
|
||||
<script-file value="$PROJECT_DIR$/src/main/resources/sql/functions/opinion/upsert_opinion_choice.sql" />
|
||||
<script-file value="$PROJECT_DIR$/src/test/sql/opinion.sql" />
|
||||
<script-mode>FILE</script-mode>
|
||||
<data-source id="a9a6d0e9-327d-4e7d-9b93-3cb6f7948866" namespace="database/"test"/schema/"public"" />
|
||||
|
||||
24
.idea/runConfigurations/Vote_Tests.xml
generated
Normal file
24
.idea/runConfigurations/Vote_Tests.xml
generated
Normal file
@@ -0,0 +1,24 @@
|
||||
<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="RunCucumberTest" />
|
||||
<option name="METHOD_NAME" value="" />
|
||||
<option name="TEST_OBJECT" value="class" />
|
||||
<option name="VM_PARAMETERS" value="-ea -Dcucumber.filter.tags="@vote"" />
|
||||
<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>
|
||||
29
.idea/runConfigurations/Voter_Tests.xml
generated
Normal file
29
.idea/runConfigurations/Voter_Tests.xml
generated
Normal file
@@ -0,0 +1,29 @@
|
||||
<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 />
|
||||
<extension name="coverage">
|
||||
<pattern>
|
||||
<option name="PATTERN" value="fr.dcproject.security.voter.*" />
|
||||
<option name="ENABLED" value="true" />
|
||||
</pattern>
|
||||
</extension>
|
||||
<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>
|
||||
3
.idea/runConfigurations/Workgroup_test.xml
generated
3
.idea/runConfigurations/Workgroup_test.xml
generated
@@ -1,5 +1,5 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="Workgroup test" type="JUnit" factoryName="JUnit" show_console_on_std_err="true">
|
||||
<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 />
|
||||
@@ -25,7 +25,6 @@
|
||||
<tag value="!online" />
|
||||
<method v="2">
|
||||
<option name="Make" enabled="true" />
|
||||
<option name="RunConfigurationTask" enabled="true" run_configuration_name="Test Workgroup" run_configuration_type="DatabaseScript" />
|
||||
</method>
|
||||
</configuration>
|
||||
</component>
|
||||
@@ -8,7 +8,7 @@ import fr.postgresjson.entity.mutable.EntityDeletedAtImp
|
||||
import java.util.*
|
||||
|
||||
class OpinionChoice(
|
||||
id: UUID,
|
||||
id: UUID? = null,
|
||||
val name: String,
|
||||
val target: List<String>?
|
||||
) : OpinionChoiceRef(id),
|
||||
@@ -16,5 +16,5 @@ class OpinionChoice(
|
||||
EntityDeletedAt by EntityDeletedAtImp()
|
||||
|
||||
open class OpinionChoiceRef(
|
||||
id: UUID
|
||||
) : UuidEntity(id)
|
||||
id: UUID?
|
||||
) : UuidEntity(id ?: UUID.randomUUID())
|
||||
@@ -6,7 +6,7 @@ import fr.postgresjson.entity.mutable.EntityDeletedAtImp
|
||||
import java.util.*
|
||||
|
||||
class Workgroup(
|
||||
id: UUID?,
|
||||
id: UUID? = null,
|
||||
name: String,
|
||||
description: String,
|
||||
logo: String? = null,
|
||||
@@ -28,7 +28,7 @@ class Workgroup(
|
||||
EntityUpdatedAt by EntityUpdatedAtImp()
|
||||
|
||||
open class WorkgroupSimple<Z : CitizenRef>(
|
||||
id: UUID?,
|
||||
id: UUID? = null,
|
||||
var name: String,
|
||||
var description: String,
|
||||
var logo: String? = null,
|
||||
@@ -40,7 +40,7 @@ open class WorkgroupSimple<Z : CitizenRef>(
|
||||
EntityDeletedAt by EntityDeletedAtImp()
|
||||
|
||||
open class WorkgroupRef(
|
||||
id: UUID?
|
||||
id: UUID? = null
|
||||
) : UuidEntity(id ?: UUID.randomUUID()), WorkgroupI
|
||||
|
||||
interface WorkgroupWithAuthI<Z : CitizenWithUserI> : WorkgroupWithMembersI<Z>, EntityCreatedBy<Z>, EntityDeletedAt {
|
||||
|
||||
@@ -43,6 +43,12 @@ open class OpinionChoice(override val requester: Requester) : RepositoryI {
|
||||
.selectOne(
|
||||
"id" to id
|
||||
)
|
||||
|
||||
fun upsertOpinionChoice(opinionChoice: OpinionChoiceEntity): OpinionChoiceEntity = requester
|
||||
.getFunction("upsert_opinion_choice")
|
||||
.selectOne(
|
||||
"resource" to opinionChoice
|
||||
)!!
|
||||
}
|
||||
|
||||
open class Opinion<T : TargetRef>(requester: Requester) : OpinionChoice(requester) {
|
||||
|
||||
@@ -34,9 +34,6 @@ object ConstitutionPaths {
|
||||
@Location("/constitutions/{constitution}")
|
||||
class ConstitutionRequest(val constitution: ConstitutionEntity)
|
||||
|
||||
@Location("/constitutions/{constitution}/follow")
|
||||
class ConstitutionFollowRequest(val constitution: ConstitutionEntity)
|
||||
|
||||
@Location("/constitutions")
|
||||
class PostConstitutionRequest
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ import fr.dcproject.repository.FollowConstitution as FollowConstitutionRepositor
|
||||
|
||||
@KtorExperimentalLocationsAPI
|
||||
object FollowConstitutionPaths {
|
||||
@Location("/constitutions/{constitution}/follow")
|
||||
@Location("/constitutions/{constitution}/follows")
|
||||
class ConstitutionFollowRequest(val constitution: ConstitutionRef)
|
||||
|
||||
@Location("/citizens/{citizen}/follows/constitutions")
|
||||
@@ -38,6 +38,13 @@ fun Route.followConstitution(repo: FollowConstitutionRepository) {
|
||||
call.respond(HttpStatusCode.NoContent)
|
||||
}
|
||||
|
||||
get<FollowConstitutionPaths.ConstitutionFollowRequest> {
|
||||
repo.findFollow(citizen, it.constitution)?.let { follow ->
|
||||
assertCan(VIEW, follow)
|
||||
call.respond(follow)
|
||||
} ?: call.respond(HttpStatusCode.NotFound)
|
||||
}
|
||||
|
||||
get<FollowConstitutionPaths.CitizenFollowConstitutionRequest> {
|
||||
val follows = repo.findByCitizen(it.citizen)
|
||||
assertCan(VIEW, follows.result)
|
||||
|
||||
@@ -2,7 +2,6 @@ package fr.dcproject.security.voter
|
||||
|
||||
import fr.dcproject.entity.ArticleAuthI
|
||||
import fr.dcproject.entity.ArticleI
|
||||
import fr.dcproject.entity.ArticleSimpleI
|
||||
import fr.dcproject.entity.UserI
|
||||
import io.ktor.application.ApplicationCall
|
||||
import fr.dcproject.entity.Comment as CommentEntity
|
||||
@@ -27,7 +26,7 @@ class ArticleVoter : Voter {
|
||||
if (action == Action.VIEW) return view(subject, user)
|
||||
if (action == Action.DELETE) return delete(subject, user)
|
||||
if (action == Action.UPDATE) return update(subject, user)
|
||||
if (action is CommentVoter.Action) return voteForComment(action)
|
||||
if (action is CommentVoter.Action) return voteForComment(action, subject)
|
||||
if (action is VoteVoter.Action) return voteForVote(action, subject)
|
||||
if (action is Action) return Vote.DENIED
|
||||
|
||||
@@ -67,23 +66,36 @@ class ArticleVoter : Voter {
|
||||
private fun voteForVote(action: VoteVoter.Action, subject: Any?): Vote {
|
||||
if (action == VoteVoter.Action.CREATE && subject is VoteEntity<*>) {
|
||||
val target = subject.target
|
||||
if (target !is ArticleSimpleI) {
|
||||
return Vote.ABSTAIN
|
||||
}
|
||||
if (target.isDeleted()) {
|
||||
if (target is ArticleAuthI<*>) {
|
||||
if (target.isDeleted()) {
|
||||
return Vote.DENIED
|
||||
}
|
||||
} else if (target is ArticleI) {
|
||||
return Vote.DENIED
|
||||
}
|
||||
}
|
||||
return Vote.ABSTAIN
|
||||
}
|
||||
|
||||
private fun voteForComment(action: CommentVoter.Action): Vote {
|
||||
if (action == CommentVoter.Action.CREATE) {
|
||||
return Vote.GRANTED
|
||||
}
|
||||
private fun voteForComment(action: CommentVoter.Action, subject: Any?): Vote {
|
||||
if (subject is CommentEntity<*>) {
|
||||
val target = subject.target
|
||||
if (target is ArticleAuthI<*>) {
|
||||
if (target.isDeleted()) {
|
||||
return Vote.DENIED
|
||||
}
|
||||
} else if (target is ArticleI) {
|
||||
return Vote.DENIED
|
||||
}
|
||||
if (action == CommentVoter.Action.CREATE) {
|
||||
return Vote.GRANTED
|
||||
}
|
||||
|
||||
if (action == CommentVoter.Action.VIEW) {
|
||||
return Vote.GRANTED
|
||||
if (action == CommentVoter.Action.VIEW) {
|
||||
return Vote.GRANTED
|
||||
}
|
||||
} else {
|
||||
return Vote.DENIED
|
||||
}
|
||||
|
||||
return Vote.ABSTAIN
|
||||
|
||||
@@ -17,7 +17,7 @@ class CitizenVoter : Voter {
|
||||
|
||||
override fun supports(action: ActionI, call: ApplicationCall, subject: Any?): Boolean {
|
||||
return (action is Action)
|
||||
.and(subject is List<*> || subject is CitizenBasicI?)
|
||||
.and(subject is CitizenBasicI?)
|
||||
}
|
||||
|
||||
override fun vote(action: ActionI, call: ApplicationCall, subject: Any?): Vote {
|
||||
@@ -32,14 +32,6 @@ class CitizenVoter : Voter {
|
||||
return if (subject.isDeleted()) Vote.DENIED
|
||||
else Vote.GRANTED
|
||||
}
|
||||
if (subject is List<*>) {
|
||||
subject.forEach {
|
||||
if (it !is CitizenBasicI || it.isDeleted()) {
|
||||
return Vote.DENIED
|
||||
}
|
||||
}
|
||||
return Vote.GRANTED
|
||||
}
|
||||
return Vote.DENIED
|
||||
}
|
||||
|
||||
|
||||
@@ -13,32 +13,32 @@ class CommentVoter : Voter {
|
||||
|
||||
override fun supports(action: ActionI, call: ApplicationCall, subject: Any?): Boolean {
|
||||
return (action is Action)
|
||||
.and(subject is Comment<*>? || subject is List<*>)
|
||||
.and(subject is Comment<*>?)
|
||||
}
|
||||
|
||||
override fun vote(action: ActionI, call: ApplicationCall, subject: Any?): Vote {
|
||||
val user = call.user
|
||||
if (action == Action.CREATE && user != null) {
|
||||
|
||||
if (subject !is Comment<*>) {
|
||||
return Vote.DENIED
|
||||
}
|
||||
|
||||
if (action == Action.CREATE) {
|
||||
if (user == null) {
|
||||
return Vote.DENIED
|
||||
}
|
||||
if (subject.createdBy.user.id != user.id) {
|
||||
return Vote.DENIED
|
||||
}
|
||||
return Vote.GRANTED
|
||||
}
|
||||
|
||||
if (action == Action.VIEW) {
|
||||
if (subject is Comment<*>) {
|
||||
return if (subject.isDeleted()) Vote.DENIED
|
||||
else Vote.GRANTED
|
||||
}
|
||||
if (subject is List<*>) {
|
||||
subject.forEach {
|
||||
if (it !is Comment<*> || it.isDeleted()) {
|
||||
return Vote.DENIED
|
||||
}
|
||||
}
|
||||
return Vote.GRANTED
|
||||
}
|
||||
return Vote.DENIED
|
||||
return if (subject.isDeleted()) Vote.DENIED
|
||||
else Vote.GRANTED
|
||||
}
|
||||
|
||||
if (action == Action.UPDATE && user != null && subject is Comment<*> && user.id == subject.createdBy.user.id) {
|
||||
if (action == Action.UPDATE && user != null && user.id == subject.createdBy.user.id) {
|
||||
return Vote.GRANTED
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ class ConstitutionVoter : Voter {
|
||||
|
||||
override fun supports(action: ActionI, call: ApplicationCall, subject: Any?): Boolean {
|
||||
return (action is Action || action is CommentVoter.Action || action is VoteVoter.Action)
|
||||
.and(subject is List<*> || subject is ConstitutionSimple<*, *>? || subject is VoteEntity<*> || subject is Comment<*>)
|
||||
.and(subject is ConstitutionSimple<*, *>? || subject is VoteEntity<*> || subject is Comment<*>)
|
||||
}
|
||||
|
||||
override fun vote(action: ActionI, call: ApplicationCall, subject: Any?): Vote {
|
||||
@@ -30,14 +30,6 @@ class ConstitutionVoter : Voter {
|
||||
return if (subject.isDeleted()) Vote.DENIED
|
||||
else Vote.GRANTED
|
||||
}
|
||||
if (subject is List<*>) {
|
||||
subject.forEach {
|
||||
if (it !is ConstitutionSimple<*, *> || it.isDeleted()) {
|
||||
return Vote.DENIED
|
||||
}
|
||||
}
|
||||
return Vote.GRANTED
|
||||
}
|
||||
return Vote.DENIED
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ class FollowVoter : Voter {
|
||||
|
||||
override fun supports(action: ActionI, call: ApplicationCall, subject: Any?): Boolean {
|
||||
return (action is Action)
|
||||
.and(subject is List<*> || subject is FollowEntity<*>?)
|
||||
.and(subject is FollowEntity<*>?)
|
||||
}
|
||||
|
||||
override fun vote(action: ActionI, call: ApplicationCall, subject: Any?): Vote {
|
||||
@@ -32,14 +32,6 @@ class FollowVoter : Voter {
|
||||
if (subject is FollowEntity<*>) {
|
||||
return voteView(user, subject)
|
||||
}
|
||||
if (subject is List<*>) {
|
||||
subject.forEach {
|
||||
if (it !is FollowEntity<*> || voteView(user, it) == Vote.DENIED) {
|
||||
return Vote.DENIED
|
||||
}
|
||||
}
|
||||
return Vote.GRANTED
|
||||
}
|
||||
return Vote.DENIED
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ class OpinionChoiceVoter : Voter {
|
||||
|
||||
override fun supports(action: ActionI, call: ApplicationCall, subject: Any?): Boolean {
|
||||
return (action is Action)
|
||||
.and(subject is OpinionChoice? || subject is List<*>)
|
||||
.and(subject is OpinionChoice?)
|
||||
}
|
||||
|
||||
override fun vote(action: ActionI, call: ApplicationCall, subject: Any?): Vote {
|
||||
@@ -18,14 +18,6 @@ class OpinionChoiceVoter : Voter {
|
||||
if (subject is OpinionChoice) {
|
||||
return Vote.GRANTED
|
||||
}
|
||||
if (subject is List<*>) {
|
||||
subject.forEach {
|
||||
if (it !is OpinionChoice) {
|
||||
return Vote.DENIED
|
||||
}
|
||||
}
|
||||
return Vote.GRANTED
|
||||
}
|
||||
return Vote.DENIED
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ class OpinionVoter : Voter {
|
||||
|
||||
override fun supports(action: ActionI, call: ApplicationCall, subject: Any?): Boolean {
|
||||
return (action is Action)
|
||||
.and(subject is Opinion<*>? || subject is List<*>)
|
||||
.and(subject is Opinion<*>?)
|
||||
}
|
||||
|
||||
override fun vote(action: ActionI, call: ApplicationCall, subject: Any?): Vote {
|
||||
@@ -25,14 +25,6 @@ class OpinionVoter : Voter {
|
||||
if (subject is Opinion<*>) {
|
||||
return Vote.GRANTED
|
||||
}
|
||||
if (subject is List<*>) {
|
||||
subject.forEach {
|
||||
if (it !is Opinion<*>) {
|
||||
return Vote.DENIED
|
||||
}
|
||||
}
|
||||
return Vote.GRANTED
|
||||
}
|
||||
return Vote.DENIED
|
||||
}
|
||||
|
||||
@@ -45,10 +37,6 @@ class OpinionVoter : Voter {
|
||||
else Vote.DENIED
|
||||
}
|
||||
|
||||
if (action is Action) {
|
||||
return Vote.DENIED
|
||||
}
|
||||
|
||||
return Vote.ABSTAIN
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,10 +10,7 @@ class VoteVoter : Voter {
|
||||
}
|
||||
|
||||
override fun supports(action: ActionI, call: ApplicationCall, subject: Any?): Boolean {
|
||||
return action is Action && (
|
||||
subject is VoteEntity<*>? ||
|
||||
subject is List<*>
|
||||
)
|
||||
return action is Action && subject is VoteEntity<*>?
|
||||
}
|
||||
|
||||
override fun vote(action: ActionI, call: ApplicationCall, subject: Any?): Vote {
|
||||
@@ -30,16 +27,6 @@ class VoteVoter : Voter {
|
||||
Vote.GRANTED
|
||||
}
|
||||
}
|
||||
|
||||
if (subject is List<*>) {
|
||||
subject.forEach {
|
||||
if (it !is VoteEntity<*> || it.createdBy.user.id != user.id) {
|
||||
return Vote.DENIED
|
||||
}
|
||||
}
|
||||
return Vote.GRANTED
|
||||
}
|
||||
|
||||
return Vote.DENIED
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ class WorkgroupVoter : Voter {
|
||||
|
||||
override fun supports(action: ActionI, call: ApplicationCall, subject: Any?): Boolean {
|
||||
return (action is Action)
|
||||
.and(subject is List<*> || subject is WorkgroupI?)
|
||||
.and(subject is WorkgroupI?)
|
||||
}
|
||||
|
||||
override fun vote(action: ActionI, call: ApplicationCall, subject: Any?): Vote {
|
||||
@@ -31,14 +31,6 @@ class WorkgroupVoter : Voter {
|
||||
else if (subject.anonymous && user != null && subject.isMember(user)) Vote.GRANTED
|
||||
else Vote.DENIED
|
||||
}
|
||||
if (subject is List<*>) {
|
||||
subject.forEach {
|
||||
if (it !is WorkgroupWithAuthI<*> || it.isDeleted()) {
|
||||
return Vote.DENIED
|
||||
}
|
||||
}
|
||||
return Vote.GRANTED
|
||||
}
|
||||
return Vote.DENIED
|
||||
}
|
||||
|
||||
@@ -52,10 +44,9 @@ class WorkgroupVoter : Voter {
|
||||
}
|
||||
|
||||
return Vote.DENIED
|
||||
}
|
||||
|
||||
if (action is Action) {
|
||||
return Vote.DENIED
|
||||
} else if (subject !is WorkgroupWithAuthI<*> && (action == Action.DELETE || action == Action.UPDATE)) {
|
||||
throw object :
|
||||
VoterException("Unable to define if your are granted, the subject must implement 'WorkgroupWithAuthI'") {}
|
||||
}
|
||||
|
||||
return Vote.ABSTAIN
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
create or replace function upsert_opinion_choice(inout resource json)
|
||||
language plpgsql as
|
||||
$$
|
||||
declare
|
||||
_id uuid = coalesce((resource->>'id')::uuid, uuid_generate_v4());
|
||||
begin
|
||||
insert into opinion_choice (id, name, target)
|
||||
select
|
||||
_id,
|
||||
name,
|
||||
target
|
||||
from json_populate_record(null::opinion_choice, resource)
|
||||
on conflict (name) do update set
|
||||
target = excluded.target;
|
||||
|
||||
select find_opinion_choice_by_id(_id) into resource;
|
||||
end;
|
||||
$$;
|
||||
|
||||
-- drop function if exists upsert_opinion_choice(json);
|
||||
@@ -35,10 +35,10 @@ class FollowTest {
|
||||
"username":"jaque",
|
||||
"blocked_at":null,
|
||||
"plain_password":"azerty",
|
||||
"created_at":null,
|
||||
"updated_at":null
|
||||
"created_at":"2019-08-09T11:42:47.168Z",
|
||||
"updated_at":"2019-08-09T11:42:47.168Z"
|
||||
},
|
||||
"created_at":null
|
||||
"created_at":"2019-08-09T11:42:47.168Z"
|
||||
},
|
||||
"target":{
|
||||
"id":"34588ea7-c180-4694-801b-1b5c5a6ed73f",
|
||||
@@ -66,15 +66,15 @@ class FollowTest {
|
||||
"username":"jaque",
|
||||
"blocked_at":null,
|
||||
"plain_password":"azerty",
|
||||
"created_at":null,
|
||||
"updated_at":null
|
||||
"created_at":"2019-08-09T11:42:47.168Z",
|
||||
"updated_at":"2019-08-09T11:42:47.168Z"
|
||||
}
|
||||
},
|
||||
"version_id":"a4aa7dd4-d174-42d2-9ba5-ae6f1129ffce",
|
||||
"version_number":null,
|
||||
"created_at":null
|
||||
},
|
||||
"created_at":null
|
||||
"created_at":"2019-08-09T11:42:47.168Z"
|
||||
}""".trimIndent()
|
||||
|
||||
@Test
|
||||
|
||||
@@ -42,7 +42,6 @@ class RunCucumberTest : En, KoinTest {
|
||||
|
||||
withTestApplication({ module(CUCUMBER) }) {
|
||||
migrations()
|
||||
fixtures()
|
||||
}
|
||||
unitialized = true
|
||||
}
|
||||
|
||||
@@ -72,12 +72,12 @@ class VoteTest {
|
||||
"blocked_at": null,
|
||||
"plain_password": "azerty",
|
||||
"roles": [],
|
||||
"created_at": null,
|
||||
"updated_at": null
|
||||
"created_at": "2019-08-09T11:42:47.168Z",
|
||||
"updated_at": "2019-08-09T11:42:47.168Z"
|
||||
},
|
||||
"deleted": false,
|
||||
"created_at": null,
|
||||
"deleted_at": null
|
||||
"created_at": "2019-08-09T11:42:47.168Z",
|
||||
"deleted_at": "2019-08-09T11:42:47.168Z"
|
||||
},
|
||||
"votes": {
|
||||
"up": 0,
|
||||
|
||||
@@ -9,7 +9,6 @@ import org.joda.time.DateTime
|
||||
import org.koin.test.KoinTest
|
||||
import org.koin.test.get
|
||||
import java.util.*
|
||||
import java.util.concurrent.CompletionException
|
||||
import fr.dcproject.entity.Article as ArticleEntity
|
||||
import fr.dcproject.entity.Comment as CommentEntity
|
||||
import fr.dcproject.entity.User as UserEntity
|
||||
@@ -18,93 +17,77 @@ import fr.dcproject.repository.Citizen as CitizenRepository
|
||||
|
||||
class ArticleSteps : En, KoinTest {
|
||||
init {
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
Given("I have article with id {string}") { id: String ->
|
||||
var citizen = Citizen(
|
||||
name = CitizenI.Name("John", "Doe"),
|
||||
email = "john.doe@gmail.com",
|
||||
birthday = DateTime.now(),
|
||||
user = UserEntity(username = "john-doe", plainPassword = "azerty")
|
||||
)
|
||||
|
||||
try {
|
||||
get<CitizenRepository>().insertWithUser(citizen)
|
||||
} catch (e: CompletionException) {
|
||||
citizen = get<CitizenRepository>().findByUsername("john-doe")!!
|
||||
}
|
||||
|
||||
val article = ArticleEntity(
|
||||
id = UUID.fromString(id),
|
||||
title = "hello",
|
||||
content = "bla bla bla",
|
||||
description = "A super article",
|
||||
createdBy = citizen
|
||||
)
|
||||
get<ArticleRepository>().upsert(article)
|
||||
}
|
||||
|
||||
Given("I have article") { extraData: DataTable ->
|
||||
extraData.asMap<String, String>(String::class.java, String::class.java).let { params ->
|
||||
val username = params["createdBy"]?.toLowerCase()?.replace(' ', '-')
|
||||
?: error("You must provide the 'createdBy' parameter")
|
||||
val citizen = get<CitizenRepository>().findByUsername(username) ?: error("Citizen not exist")
|
||||
val id = params["id"]?.toUUID() ?: UUID.randomUUID()
|
||||
val article = ArticleEntity(
|
||||
id = id,
|
||||
title = "hello",
|
||||
content = "bla bla bla",
|
||||
description = "A super article",
|
||||
createdBy = citizen
|
||||
)
|
||||
get<ArticleRepository>().upsert(article)
|
||||
Given("I have {int} article") { nb: Int ->
|
||||
repeat(nb) {
|
||||
createArticle()
|
||||
}
|
||||
}
|
||||
|
||||
Given("I have article with id {string} created by {string}") { id: String, username: String ->
|
||||
val citizen = get<CitizenRepository>().findByUsername(username)!!
|
||||
|
||||
val article = ArticleEntity(
|
||||
id = UUID.fromString(id),
|
||||
title = "hello",
|
||||
content = "bla bla bla",
|
||||
description = "A super article",
|
||||
createdBy = citizen
|
||||
)
|
||||
get<ArticleRepository>().upsert(article)
|
||||
Given("I have article") { extraData: DataTable? ->
|
||||
createArticle(extraData)
|
||||
}
|
||||
|
||||
Given("I have comment {string} on article {string}") { commentId: String, articleId: String ->
|
||||
var citizen = Citizen(
|
||||
name = CitizenI.Name("John", "Doe"),
|
||||
email = "john.doe@gmail.com",
|
||||
birthday = DateTime.now(),
|
||||
user = UserEntity(username = "john-doe", plainPassword = "azerty")
|
||||
)
|
||||
Given("I have article with ID {string}") { id: String ->
|
||||
createArticle(id = UUID.fromString(id))
|
||||
}
|
||||
|
||||
try {
|
||||
get<CitizenRepository>().insertWithUser(citizen)
|
||||
} catch (e: CompletionException) {
|
||||
citizen = get<CitizenRepository>().findByUsername("john-doe")!!
|
||||
}
|
||||
|
||||
val article = ArticleEntity(
|
||||
id = UUID.fromString(articleId),
|
||||
title = "hello",
|
||||
content = "bla bla bla",
|
||||
description = "A super article",
|
||||
createdBy = citizen
|
||||
)
|
||||
get<ArticleRepository>().upsert(article)
|
||||
|
||||
val comment: CommentEntity<ArticleRef> = CommentEntity(
|
||||
id = UUID.fromString(commentId),
|
||||
createdBy = citizen,
|
||||
target = article,
|
||||
content = "hello"
|
||||
)
|
||||
get<CommentArticle>().comment(comment)
|
||||
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) {
|
||||
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()
|
||||
Citizen(
|
||||
birthday = DateTime.now(),
|
||||
name = CitizenI.Name(
|
||||
first,
|
||||
last
|
||||
),
|
||||
email = "$first@fakeemail.com",
|
||||
user = UserEntity(username = username, plainPassword = "azerty")
|
||||
).also {
|
||||
get<CitizenRepository>().insertWithUser(it)
|
||||
}
|
||||
}
|
||||
|
||||
val article = ArticleEntity(
|
||||
id = id ?: params?.get("id")?.toUUID() ?: UUID.randomUUID(),
|
||||
title = "hello",
|
||||
content = "bla bla bla",
|
||||
description = "A super article",
|
||||
createdBy = createdBy
|
||||
)
|
||||
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: CommentEntity<ArticleRef> = CommentEntity(
|
||||
id = id ?: params?.get("id")?.let { UUID.fromString(it) } ?: UUID.randomUUID(),
|
||||
createdBy = citizen,
|
||||
target = article,
|
||||
content = params?.get("content") ?: "hello"
|
||||
)
|
||||
get<CommentArticle>().comment(comment)
|
||||
}
|
||||
}
|
||||
55
src/test/kotlin/feature/CitizenSteps.kt
Normal file
55
src/test/kotlin/feature/CitizenSteps.kt
Normal file
@@ -0,0 +1,55 @@
|
||||
package feature
|
||||
|
||||
import fr.dcproject.entity.Citizen
|
||||
import fr.dcproject.entity.CitizenI
|
||||
import fr.dcproject.entity.User
|
||||
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.*
|
||||
import fr.dcproject.repository.Citizen as CitizenRepository
|
||||
|
||||
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 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 = User(
|
||||
id = id,
|
||||
username = "$firstName-$lastName".toLowerCase(),
|
||||
plainPassword = "azerty"
|
||||
)
|
||||
val citizen = Citizen(
|
||||
id = id,
|
||||
name = CitizenI.Name(firstName, lastName),
|
||||
email = email,
|
||||
birthday = DateTime.now(),
|
||||
user = user
|
||||
)
|
||||
|
||||
get<CitizenRepository>().insertWithUser(citizen)
|
||||
}
|
||||
}
|
||||
@@ -1,62 +1,102 @@
|
||||
package feature
|
||||
|
||||
import fr.dcproject.entity.*
|
||||
import fr.dcproject.entity.ConstitutionSimple.TitleSimple
|
||||
import fr.dcproject.entity.request.Constitution
|
||||
import fr.dcproject.repository.CommentConstitution
|
||||
import fr.dcproject.utils.toUUID
|
||||
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.*
|
||||
import java.util.concurrent.CompletionException
|
||||
import fr.dcproject.entity.Comment as CommentEntity
|
||||
import fr.dcproject.entity.User as UserEntity
|
||||
import fr.dcproject.repository.Citizen as CitizenRepository
|
||||
import fr.dcproject.repository.Constitution as ConstitutionRepository
|
||||
|
||||
class ConstitutionSteps : En, KoinTest {
|
||||
init {
|
||||
Given("I have constitution with id {string}") { id: String ->
|
||||
var citizen = Citizen(
|
||||
id = UUID.fromString(id),
|
||||
name = CitizenI.Name("John", "Doe"),
|
||||
email = "john.doe@gmail.com",
|
||||
birthday = DateTime.now(),
|
||||
user = UserEntity(username = "john-doe", plainPassword = "azerty")
|
||||
)
|
||||
|
||||
try {
|
||||
get<CitizenRepository>().insertWithUser(citizen)
|
||||
} catch (e: CompletionException) {
|
||||
citizen = get<CitizenRepository>().findByUsername("john-doe")!!
|
||||
Given("I have {int} constitution") { nb: Int ->
|
||||
repeat(nb) {
|
||||
createConstitution()
|
||||
}
|
||||
|
||||
val title1 = Constitution.Title(
|
||||
name = "My Title"
|
||||
)
|
||||
|
||||
val constitution = Constitution(
|
||||
title = "hello",
|
||||
titles = mutableListOf(title1),
|
||||
anonymous = false
|
||||
)
|
||||
get<ConstitutionRepository>().upsert(constitution.create(citizen))
|
||||
}
|
||||
|
||||
Given("I have constitution with id {string} created by {string}") { id: String, username: String ->
|
||||
val citizen = get<CitizenRepository>().findByUsername(username)!!
|
||||
Given("I have constitution") { extraData: DataTable? ->
|
||||
createConstitution(extraData)
|
||||
}
|
||||
|
||||
val title1 = TitleSimple<ArticleRef>(
|
||||
name = "My Title"
|
||||
)
|
||||
Given("I have constitution with ID {string}") { id: String? ->
|
||||
createConstitution(id = UUID.fromString(id))
|
||||
}
|
||||
|
||||
val constitution = ConstitutionSimple<CitizenSimple, TitleSimple<ArticleRef>>(
|
||||
id = UUID.fromString(id),
|
||||
title = "hello",
|
||||
titles = mutableListOf(title1),
|
||||
anonymous = false,
|
||||
createdBy = citizen
|
||||
)
|
||||
get<ConstitutionRepository>().upsert(constitution)
|
||||
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()
|
||||
Citizen(
|
||||
birthday = DateTime.now(),
|
||||
name = CitizenI.Name(
|
||||
first,
|
||||
last
|
||||
),
|
||||
email = "$first@fakeemail.com",
|
||||
user = UserEntity(username = username, plainPassword = "azerty")
|
||||
).also {
|
||||
get<CitizenRepository>().insertWithUser(it)
|
||||
}
|
||||
}
|
||||
|
||||
val title1 = ConstitutionSimple.TitleSimple<ArticleRef>(
|
||||
name = "My Title"
|
||||
)
|
||||
|
||||
val constitution = ConstitutionSimple<CitizenSimple, ConstitutionSimple.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: CommentEntity<ConstitutionRef> = CommentEntity(
|
||||
id = params?.get("id")?.let { UUID.fromString(it) } ?: UUID.randomUUID(),
|
||||
createdBy = citizen,
|
||||
target = constitution,
|
||||
content = params?.get("content") ?: "hello"
|
||||
)
|
||||
get<CommentConstitution>().comment(comment)
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package feature
|
||||
|
||||
import fr.dcproject.entity.ArticleRef
|
||||
import fr.dcproject.entity.ConstitutionRef
|
||||
import fr.dcproject.entity.Follow
|
||||
import fr.dcproject.utils.toUUID
|
||||
import io.cucumber.java8.En
|
||||
@@ -8,14 +9,21 @@ import org.koin.test.KoinTest
|
||||
import org.koin.test.get
|
||||
import fr.dcproject.repository.Citizen as CitizenRepository
|
||||
import fr.dcproject.repository.FollowArticle as FollowArticleRepository
|
||||
import fr.dcproject.repository.FollowConstitution as FollowConstitutionRepository
|
||||
|
||||
class FollowSteps : En, KoinTest {
|
||||
init {
|
||||
Given("The citizen {word} {word} follow article {string}") { firstName: String, lastName: String, articleId: String ->
|
||||
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 = Follow(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 = Follow(createdBy = citizen, target = ConstitutionRef(constitutionId.toUUID()))
|
||||
get<FollowConstitutionRepository>().follow(follow)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,91 +2,14 @@ package feature
|
||||
|
||||
import com.auth0.jwt.JWT
|
||||
import fr.dcproject.JwtConfig
|
||||
import fr.dcproject.entity.Citizen
|
||||
import fr.dcproject.entity.CitizenI
|
||||
import fr.dcproject.entity.User
|
||||
import fr.postgresjson.connexion.Requester
|
||||
import io.cucumber.datatable.DataTable
|
||||
import io.cucumber.java8.En
|
||||
import io.ktor.http.HttpHeaders
|
||||
import org.joda.time.DateTime
|
||||
import org.koin.test.KoinTest
|
||||
import org.koin.test.get
|
||||
import org.koin.test.inject
|
||||
import java.util.*
|
||||
import java.util.concurrent.CompletionException
|
||||
import fr.dcproject.repository.Citizen as CitizenRepository
|
||||
|
||||
class KtorServerAuthSteps : En, KoinTest {
|
||||
private val requester: Requester by inject()
|
||||
init {
|
||||
When("I have citizen:") { body: DataTable ->
|
||||
val data = body.asMap<String, String>(String::class.java, String::class.java)
|
||||
val username = (data["firstName"] + "-" + data["lastName"]).toLowerCase()
|
||||
val user = User(
|
||||
username = username,
|
||||
plainPassword = "azerty"
|
||||
)
|
||||
val citizen = Citizen(
|
||||
id = UUID.fromString(data["id"]),
|
||||
name = CitizenI.Name(data["firstName"]!!, data["lastName"]!!),
|
||||
email = data["email"] ?: "$username@dc-project.com",
|
||||
birthday = DateTime.now(),
|
||||
user = user
|
||||
)
|
||||
|
||||
get<CitizenRepository>().insertWithUser(citizen)
|
||||
}
|
||||
|
||||
Given("I am authenticated as {word} {word} with id {string}") { firstName: String, lastName: String, id: String ->
|
||||
val jwtAsString: String = JWT.create()
|
||||
.withIssuer("dc-project.fr")
|
||||
.withClaim("id", id)
|
||||
.sign(JwtConfig.algorithm)
|
||||
|
||||
val user = User(
|
||||
id = UUID.fromString(id),
|
||||
username = "$firstName-$lastName".toLowerCase(),
|
||||
plainPassword = "azerty"
|
||||
)
|
||||
val citizen = Citizen(
|
||||
id = UUID.fromString(id),
|
||||
name = CitizenI.Name(firstName, lastName),
|
||||
email = ("$firstName-$lastName".toLowerCase()) + "@dc-project.fr",
|
||||
birthday = DateTime.now(),
|
||||
user = user
|
||||
)
|
||||
|
||||
try {
|
||||
get<CitizenRepository>().insertWithUser(citizen)
|
||||
} catch (e: CompletionException) {
|
||||
// Nothing
|
||||
}
|
||||
|
||||
KtorServerContext.defaultServer.addPreRequestSetup {
|
||||
addHeader(HttpHeaders.Authorization, "Bearer $jwtAsString")
|
||||
}
|
||||
}
|
||||
|
||||
Given("I have citizen {word} {word}") { firstName: String, lastName: String ->
|
||||
val id: UUID = UUID.randomUUID()
|
||||
|
||||
val user = User(
|
||||
id = id,
|
||||
username = "$firstName-$lastName".toLowerCase(),
|
||||
plainPassword = "azerty"
|
||||
)
|
||||
val citizen = Citizen(
|
||||
id = id,
|
||||
name = CitizenI.Name(firstName, lastName),
|
||||
email = ("$firstName-$lastName".toLowerCase()) + "@dc-project.fr",
|
||||
birthday = DateTime.now(),
|
||||
user = user
|
||||
)
|
||||
|
||||
get<CitizenRepository>().insertWithUser(citizen)
|
||||
}
|
||||
|
||||
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")
|
||||
@@ -99,28 +22,5 @@ class KtorServerAuthSteps : En, KoinTest {
|
||||
addHeader(HttpHeaders.Authorization, "Bearer $jwtAsString")
|
||||
}
|
||||
}
|
||||
|
||||
Given("I have citizen {word} {word} with id {string}") { firstName: String, lastName: String, id: String ->
|
||||
val user = User(
|
||||
id = UUID.randomUUID(),
|
||||
username = "$firstName-$lastName".toLowerCase(),
|
||||
plainPassword = "azerty"
|
||||
)
|
||||
val citizen = Citizen(
|
||||
id = UUID.fromString(id),
|
||||
name = CitizenI.Name(firstName, lastName),
|
||||
email = "$firstName-$lastName".toLowerCase() + "@gmail.com",
|
||||
birthday = DateTime.now(),
|
||||
user = user,
|
||||
followAnonymous = false,
|
||||
voteAnonymous = false
|
||||
)
|
||||
|
||||
try {
|
||||
get<CitizenRepository>().insertWithUser(citizen)
|
||||
} catch (e: CompletionException) {
|
||||
// Nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,13 @@
|
||||
package feature
|
||||
|
||||
import fr.dcproject.entity.OpinionArticle
|
||||
import fr.dcproject.entity.OpinionChoice
|
||||
import fr.dcproject.utils.toUUID
|
||||
import io.cucumber.datatable.DataTable
|
||||
import io.cucumber.java8.En
|
||||
import org.koin.test.KoinTest
|
||||
import org.koin.test.get
|
||||
import java.util.*
|
||||
import fr.dcproject.repository.Article as ArticleRepository
|
||||
import fr.dcproject.repository.Citizen as CitizenRepository
|
||||
import fr.dcproject.repository.OpinionArticle as OpinionRepository
|
||||
@@ -13,33 +15,60 @@ import fr.dcproject.repository.OpinionChoice as OpinionChoiceRepository
|
||||
|
||||
class OpinionSteps : En, KoinTest {
|
||||
init {
|
||||
Given("I have the opinion {string} on article {string} created by {string}:") { opinionChoice: String, article: String, citizen: String, extraInfo: DataTable ->
|
||||
extraInfo.asMap<String, String>(String::class.java, String::class.java).let {
|
||||
val opinion = OpinionArticle(
|
||||
choice = get<OpinionChoiceRepository>().findOpinionsChoiceByName(opinionChoice)
|
||||
?: error("Opinion Choice not exist"),
|
||||
target = get<ArticleRepository>().findById(article.toUUID()) ?: error("Article not exist"),
|
||||
createdBy = get<CitizenRepository>().findById(citizen.toUUID()) ?: error("Citizen not exist")
|
||||
)
|
||||
get<OpinionRepository>().opinion(opinion)
|
||||
}
|
||||
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 ->
|
||||
extraInfo.asMap<String, String>(String::class.java, String::class.java)?.let { params ->
|
||||
val username = params["createdBy"]?.toLowerCase()?.replace(' ', '-')
|
||||
?: error("You must provide the 'createdBy' parameter")
|
||||
val opinion = OpinionArticle(
|
||||
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>().opinion(opinion)
|
||||
}
|
||||
createOpinionOnArticle(extraInfo)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createOpinion(opinionChoiceName: String, articleId: String, firstName: String, lastName: String, id: String? = null) {
|
||||
val opinion = OpinionArticle(
|
||||
id = id?.toUUID() ?: UUID.randomUUID(),
|
||||
choice = get<OpinionChoiceRepository>().findOpinionsChoiceByName(opinionChoiceName)
|
||||
?: error("Opinion Choice not exist"),
|
||||
target = get<ArticleRepository>().findById(articleId.toUUID()) ?: error("Article not exist"),
|
||||
createdBy = get<CitizenRepository>().findByUsername("$firstName-$lastName".toLowerCase().replace(' ', '-')) ?: error("Citizen not exist")
|
||||
)
|
||||
get<OpinionRepository>().opinion(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 = OpinionArticle(
|
||||
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>().opinion(opinion)
|
||||
}
|
||||
}
|
||||
33
src/test/kotlin/feature/VoteSteps.kt
Normal file
33
src/test/kotlin/feature/VoteSteps.kt
Normal file
@@ -0,0 +1,33 @@
|
||||
package feature
|
||||
|
||||
import fr.dcproject.entity.Vote
|
||||
import fr.dcproject.utils.toUUID
|
||||
import io.cucumber.java8.En
|
||||
import org.koin.test.KoinTest
|
||||
import org.koin.test.get
|
||||
import java.util.*
|
||||
import fr.dcproject.repository.Article as ArticleRepository
|
||||
import fr.dcproject.repository.Citizen as CitizenRepository
|
||||
import fr.dcproject.repository.VoteArticle 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 = Vote(
|
||||
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)
|
||||
}
|
||||
}
|
||||
@@ -7,10 +7,12 @@ import io.mockk.mockk
|
||||
import io.mockk.mockkStatic
|
||||
import org.amshove.kluent.`should be`
|
||||
import org.joda.time.DateTime
|
||||
import org.junit.jupiter.api.Tag
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
@Tag("voter")
|
||||
internal class ArticleVoterTest {
|
||||
val tesla = CitizenBasic(
|
||||
user = User(
|
||||
@@ -48,15 +50,13 @@ internal class ArticleVoterTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `other user can be view the article`() = ArticleVoter().run {
|
||||
fun `other user can be view the article`() = listOf(ArticleVoter()).run {
|
||||
val article = getArticle(tesla)
|
||||
val article2 = getArticle(tesla)
|
||||
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns einstein.user
|
||||
}.let {
|
||||
supports(ArticleVoter.Action.VIEW, it, article) `should be` true
|
||||
vote(ArticleVoter.Action.VIEW, it, article) `should be` Vote.GRANTED
|
||||
can(ArticleVoter.Action.VIEW, it, article) `should be` true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,14 +73,13 @@ internal class ArticleVoterTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `the no creator can not be view the article on draft`() = ArticleVoter().run {
|
||||
fun `the no creator can not be view the article on draft`() = listOf(ArticleVoter()).run {
|
||||
val article = getArticle(tesla).apply { draft = true }
|
||||
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns einstein.user
|
||||
}.let {
|
||||
supports(ArticleVoter.Action.VIEW, it, article) `should be` true
|
||||
vote(ArticleVoter.Action.VIEW, it, article) `should be` Vote.DENIED
|
||||
can(ArticleVoter.Action.VIEW, it, article) `should be` false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,62 +96,79 @@ internal class ArticleVoterTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can not view deleted article`() = ArticleVoter().run {
|
||||
fun `can not view deleted article`() = listOf(ArticleVoter()).run {
|
||||
val article = getArticle(tesla).apply { deletedAt = DateTime.now() }
|
||||
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns tesla.user
|
||||
}.let {
|
||||
supports(ArticleVoter.Action.VIEW, it, article) `should be` true
|
||||
vote(ArticleVoter.Action.VIEW, it, article) `should be` Vote.DENIED
|
||||
can(ArticleVoter.Action.VIEW, it, article) `should be` false
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can delete article if owner`() = ArticleVoter().run {
|
||||
fun `can delete article if owner`() = listOf(ArticleVoter()).run {
|
||||
val article = getArticle(tesla)
|
||||
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns tesla.user
|
||||
}.let {
|
||||
supports(ArticleVoter.Action.DELETE, it, article) `should be` true
|
||||
vote(ArticleVoter.Action.DELETE, it, article) `should be` Vote.GRANTED
|
||||
can(ArticleVoter.Action.DELETE, it, article) `should be` true
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can not delete article if not owner`() = ArticleVoter().run {
|
||||
fun `can not delete article if not owner`() = listOf(ArticleVoter()).run {
|
||||
val article = getArticle(tesla).apply { deletedAt = DateTime.now() }
|
||||
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns einstein.user
|
||||
}.let {
|
||||
supports(ArticleVoter.Action.DELETE, it, article) `should be` true
|
||||
vote(ArticleVoter.Action.DELETE, it, article) `should be` Vote.DENIED
|
||||
can(ArticleVoter.Action.DELETE, it, article) `should be` false
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can create article if logged`() = ArticleVoter().run {
|
||||
fun `can create article if logged`() = listOf(ArticleVoter()).run {
|
||||
val article = getArticle(tesla)
|
||||
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns tesla.user
|
||||
}.let {
|
||||
supports(ArticleVoter.Action.CREATE, it, article) `should be` true
|
||||
vote(ArticleVoter.Action.CREATE, it, article) `should be` Vote.GRANTED
|
||||
can(ArticleVoter.Action.CREATE, it, article) `should be` true
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can not create article if not logged`() = ArticleVoter().run {
|
||||
fun `can not create article if not logged`() = listOf(ArticleVoter()).run {
|
||||
val article = getArticle(tesla)
|
||||
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns null
|
||||
}.let {
|
||||
supports(ArticleVoter.Action.CREATE, it, article) `should be` true
|
||||
vote(ArticleVoter.Action.CREATE, it, article) `should be` Vote.DENIED
|
||||
can(ArticleVoter.Action.CREATE, it, article) `should be` false
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can update article if yours`() = listOf(ArticleVoter()).run {
|
||||
val article = getArticle(tesla)
|
||||
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns tesla.user
|
||||
}.let {
|
||||
can(ArticleVoter.Action.UPDATE, it, article) `should be` true
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can not update article if not yours`() = listOf(ArticleVoter()).run {
|
||||
val article = getArticle(tesla)
|
||||
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns einstein.user
|
||||
}.let {
|
||||
can(ArticleVoter.Action.UPDATE, it, article) `should be` false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
125
src/test/kotlin/fr/dcproject/security/voter/CitizenVoterTest.kt
Normal file
125
src/test/kotlin/fr/dcproject/security/voter/CitizenVoterTest.kt
Normal file
@@ -0,0 +1,125 @@
|
||||
package fr.dcproject.security.voter
|
||||
|
||||
import fr.dcproject.entity.*
|
||||
import io.ktor.application.ApplicationCall
|
||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import io.mockk.mockkStatic
|
||||
import org.amshove.kluent.`should be`
|
||||
import org.joda.time.DateTime
|
||||
import org.junit.jupiter.api.Tag
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
|
||||
@KtorExperimentalLocationsAPI
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
@Tag("voter")
|
||||
internal class CitizenVoterTest {
|
||||
private val tesla = CitizenBasic(
|
||||
user = User(
|
||||
username = "nicolas-tesla",
|
||||
roles = listOf(UserI.Roles.ROLE_USER)
|
||||
),
|
||||
birthday = DateTime.now(),
|
||||
email = "tesla@best.com",
|
||||
name = CitizenI.Name("Nicolas", "Tesla")
|
||||
)
|
||||
private val einstein = CitizenBasic(
|
||||
user = User(
|
||||
username = "albert-einstein",
|
||||
roles = listOf(UserI.Roles.ROLE_USER)
|
||||
),
|
||||
birthday = DateTime.now(),
|
||||
email = "einstein@best.com",
|
||||
name = CitizenI.Name("Albert", "Einstein")
|
||||
)
|
||||
|
||||
private val curie = CitizenBasic(
|
||||
user = User(
|
||||
username = "marie-curie",
|
||||
roles = listOf(UserI.Roles.ROLE_USER)
|
||||
),
|
||||
birthday = DateTime.now(),
|
||||
email = "curie@best.com",
|
||||
name = CitizenI.Name("Marie", "Curie")
|
||||
).apply { deletedAt = DateTime.now() }
|
||||
|
||||
init {
|
||||
mockkStatic("fr.dcproject.security.voter.VoterKt")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `support citizen`() = CitizenVoter().run {
|
||||
val p = object : ActionI {}
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns tesla.user
|
||||
}.let {
|
||||
supports(CitizenVoter.Action.VIEW, it, einstein) `should be` true
|
||||
supports(p, it, einstein) `should be` false
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can be view the citizen`() = listOf(CitizenVoter()).run {
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns tesla.user
|
||||
}.let {
|
||||
can(CitizenVoter.Action.VIEW, it, einstein) `should be` true
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can be view the citizen list`() = listOf(CitizenVoter()).run {
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns einstein.user
|
||||
}.let {
|
||||
can(CitizenVoter.Action.VIEW, it, listOf(einstein, tesla)) `should be` true
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can not view deleted citizen`() = listOf(CitizenVoter()).run {
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns tesla.user
|
||||
}.let {
|
||||
can(CitizenVoter.Action.VIEW, it, curie) `should be` false
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can be update itself`() = listOf(CitizenVoter()).run {
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns einstein.user
|
||||
}.let {
|
||||
can(CitizenVoter.Action.UPDATE, it, einstein) `should be` true
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can not be update other citizen`() = listOf(CitizenVoter()).run {
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns einstein.user
|
||||
}.let {
|
||||
can(CitizenVoter.Action.UPDATE, it, tesla) `should be` false
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can be change password of itself`() = listOf(CitizenVoter()).run {
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns einstein.user
|
||||
}.let {
|
||||
can(CitizenVoter.Action.CHANGE_PASSWORD, it, einstein) `should be` true
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can not be change password of other citizen`() = listOf(CitizenVoter()).run {
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns einstein.user
|
||||
}.let {
|
||||
can(CitizenVoter.Action.CHANGE_PASSWORD, it, tesla) `should be` false
|
||||
}
|
||||
}
|
||||
}
|
||||
182
src/test/kotlin/fr/dcproject/security/voter/CommentVoterTest.kt
Normal file
182
src/test/kotlin/fr/dcproject/security/voter/CommentVoterTest.kt
Normal file
@@ -0,0 +1,182 @@
|
||||
package fr.dcproject.security.voter
|
||||
|
||||
import fr.dcproject.entity.*
|
||||
import io.ktor.application.ApplicationCall
|
||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import io.mockk.mockkStatic
|
||||
import org.amshove.kluent.`should be`
|
||||
import org.joda.time.DateTime
|
||||
import org.junit.jupiter.api.Tag
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
|
||||
@KtorExperimentalLocationsAPI
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
@Tag("voter")
|
||||
internal class CommentVoterTest {
|
||||
private val tesla = CitizenBasic(
|
||||
user = User(
|
||||
username = "nicolas-tesla",
|
||||
roles = listOf(UserI.Roles.ROLE_USER)
|
||||
),
|
||||
birthday = DateTime.now(),
|
||||
email = "tesla@best.com",
|
||||
name = CitizenI.Name("Nicolas", "Tesla")
|
||||
)
|
||||
private val einstein = CitizenBasic(
|
||||
user = User(
|
||||
username = "albert-einstein",
|
||||
roles = listOf(UserI.Roles.ROLE_USER)
|
||||
),
|
||||
birthday = DateTime.now(),
|
||||
email = "einstein@best.com",
|
||||
name = CitizenI.Name("Albert", "Einstein")
|
||||
)
|
||||
|
||||
private val article1 = Article(
|
||||
content = "Hi",
|
||||
createdBy = einstein,
|
||||
description = "blablabla",
|
||||
title = "Super article"
|
||||
)
|
||||
|
||||
private val comment1 = Comment(
|
||||
content = "Hello",
|
||||
createdBy = tesla,
|
||||
target = article1
|
||||
)
|
||||
|
||||
private val commentTargetDeleted = Comment(
|
||||
content = "Hello",
|
||||
createdBy = tesla,
|
||||
target = Article(
|
||||
content = "Hi",
|
||||
createdBy = einstein,
|
||||
description = "blablabla",
|
||||
title = "Super article"
|
||||
).apply { deletedAt = DateTime.now() }
|
||||
)
|
||||
|
||||
private val commentTargetNoUser = Comment(
|
||||
content = "Hello",
|
||||
createdBy = tesla,
|
||||
target = ArticleRef()
|
||||
)
|
||||
|
||||
init {
|
||||
mockkStatic("fr.dcproject.security.voter.VoterKt")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `support comment`() = CommentVoter().run {
|
||||
val p = object : ActionI {}
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns tesla.user
|
||||
}.let {
|
||||
supports(CommentVoter.Action.VIEW, it, comment1) `should be` true
|
||||
supports(CommentVoter.Action.VIEW, it, article1) `should be` false
|
||||
supports(p, it, comment1) `should be` false
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can be view the comment`() = listOf(CommentVoter(), ArticleVoter()).run {
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns tesla.user
|
||||
}.let {
|
||||
can(CommentVoter.Action.VIEW, it, comment1) `should be` true
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can be view the comment list`() = listOf(CommentVoter()).run {
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns einstein.user
|
||||
}.let {
|
||||
can(CommentVoter.Action.VIEW, it, listOf(comment1)) `should be` true
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can be update your comment`() = listOf(CommentVoter()).run {
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns tesla.user
|
||||
}.let {
|
||||
can(CommentVoter.Action.UPDATE, it, comment1) `should be` true
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can not be update other comment`() = listOf(CommentVoter()).run {
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns einstein.user
|
||||
}.let {
|
||||
can(CommentVoter.Action.UPDATE, it, comment1) `should be` false
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can not be delete your comment`() = listOf(CommentVoter()).run {
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns tesla.user
|
||||
}.let {
|
||||
can(CommentVoter.Action.DELETE, it, comment1) `should be` false
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can be create a comment`() = listOf(CommentVoter(), ArticleVoter()).run {
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns tesla.user
|
||||
}.let {
|
||||
can(CommentVoter.Action.CREATE, it, comment1) `should be` true
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can not be create a comment if target is deleted`() = listOf(CommentVoter(), ArticleVoter()).run {
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns tesla.user
|
||||
}.let {
|
||||
can(CommentVoter.Action.CREATE, it, commentTargetDeleted) `should be` false
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can not be create a comment if target has no user`() = listOf(CommentVoter(), ArticleVoter()).run {
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns tesla.user
|
||||
}.let {
|
||||
can(CommentVoter.Action.CREATE, it, commentTargetNoUser) `should be` false
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can not be create a comment with other creator`() = listOf(CommentVoter()).run {
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns einstein.user
|
||||
}.let {
|
||||
can(CommentVoter.Action.CREATE, it, comment1) `should be` false
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can not be create a comment if is null`() = listOf(CommentVoter()).run {
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns einstein.user
|
||||
}.let {
|
||||
can(CommentVoter.Action.CREATE, it, null) `should be` false
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can not be create a comment if not connected`() = listOf(CommentVoter()).run {
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns null
|
||||
}.let {
|
||||
can(CommentVoter.Action.CREATE, it, comment1) `should be` false
|
||||
}
|
||||
}
|
||||
}
|
||||
145
src/test/kotlin/fr/dcproject/security/voter/FollowVoterTest.kt
Normal file
145
src/test/kotlin/fr/dcproject/security/voter/FollowVoterTest.kt
Normal file
@@ -0,0 +1,145 @@
|
||||
package fr.dcproject.security.voter
|
||||
|
||||
import fr.dcproject.entity.*
|
||||
import io.ktor.application.ApplicationCall
|
||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import io.mockk.mockkStatic
|
||||
import org.amshove.kluent.`should be`
|
||||
import org.joda.time.DateTime
|
||||
import org.junit.jupiter.api.Tag
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
|
||||
@KtorExperimentalLocationsAPI
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
@Tag("voter")
|
||||
internal class FollowVoterTest {
|
||||
private val tesla = CitizenBasic(
|
||||
user = User(
|
||||
username = "nicolas-tesla",
|
||||
roles = listOf(UserI.Roles.ROLE_USER)
|
||||
),
|
||||
birthday = DateTime.now(),
|
||||
email = "tesla@best.com",
|
||||
name = CitizenI.Name("Nicolas", "Tesla"),
|
||||
followAnonymous = false
|
||||
)
|
||||
|
||||
private val einstein = CitizenBasic(
|
||||
user = User(
|
||||
username = "albert-einstein",
|
||||
roles = listOf(UserI.Roles.ROLE_USER)
|
||||
),
|
||||
birthday = DateTime.now(),
|
||||
email = "einstein@best.com",
|
||||
name = CitizenI.Name("Albert", "Einstein"),
|
||||
followAnonymous = true
|
||||
)
|
||||
|
||||
private val article1 = Article(
|
||||
content = "Hi",
|
||||
createdBy = einstein,
|
||||
description = "blablabla",
|
||||
title = "Super article"
|
||||
)
|
||||
|
||||
private val follow1 = Follow(
|
||||
createdBy = tesla,
|
||||
target = article1
|
||||
)
|
||||
|
||||
private val followAnon = Follow(
|
||||
createdBy = einstein,
|
||||
target = article1
|
||||
)
|
||||
|
||||
init {
|
||||
mockkStatic("fr.dcproject.security.voter.VoterKt")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `support follow`() = FollowVoter().run {
|
||||
val p = object : ActionI {}
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns tesla.user
|
||||
}.let {
|
||||
supports(FollowVoter.Action.VIEW, it, follow1) `should be` true
|
||||
supports(FollowVoter.Action.VIEW, it, article1) `should be` false
|
||||
supports(p, it, follow1) `should be` false
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can be view the follow`() = listOf(FollowVoter()).run {
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns tesla.user
|
||||
}.let {
|
||||
can(FollowVoter.Action.VIEW, it, follow1) `should be` true
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can be view the follow list`() = listOf(FollowVoter()).run {
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns tesla.user
|
||||
}.let {
|
||||
can(FollowVoter.Action.VIEW, it, listOf(follow1)) `should be` true
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can be view your anonymous follow`() = listOf(FollowVoter()).run {
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns einstein.user
|
||||
}.let {
|
||||
can(FollowVoter.Action.VIEW, it, followAnon) `should be` true
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can not be view the anonymous follow of other`() = listOf(FollowVoter()).run {
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns tesla.user
|
||||
}.let {
|
||||
can(FollowVoter.Action.VIEW, it, followAnon) `should be` false
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can be follow article`() = listOf(FollowVoter()).run {
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns tesla.user
|
||||
}.let {
|
||||
can(FollowVoter.Action.CREATE, it, follow1) `should be` true
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can not be follow article if not connected`() = listOf(FollowVoter()).run {
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns null
|
||||
}.let {
|
||||
can(FollowVoter.Action.CREATE, it, follow1) `should be` false
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can be unfollow article`() = listOf(FollowVoter()).run {
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns tesla.user
|
||||
}.let {
|
||||
can(FollowVoter.Action.DELETE, it, follow1) `should be` true
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can not be unfollow article if not connected`() = listOf(FollowVoter()).run {
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns null
|
||||
}.let {
|
||||
can(FollowVoter.Action.DELETE, it, follow1) `should be` false
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package fr.dcproject.security.voter
|
||||
|
||||
import fr.dcproject.entity.*
|
||||
import io.ktor.application.ApplicationCall
|
||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import io.mockk.mockkStatic
|
||||
import org.amshove.kluent.`should be`
|
||||
import org.joda.time.DateTime
|
||||
import org.junit.jupiter.api.Tag
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
|
||||
@KtorExperimentalLocationsAPI
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
@Tag("voter")
|
||||
internal class OpinionChoiceVoterTest {
|
||||
private val tesla = CitizenBasic(
|
||||
user = User(
|
||||
username = "nicolas-tesla",
|
||||
roles = listOf(UserI.Roles.ROLE_USER)
|
||||
),
|
||||
birthday = DateTime.now(),
|
||||
email = "tesla@best.com",
|
||||
name = CitizenI.Name("Nicolas", "Tesla"),
|
||||
followAnonymous = false
|
||||
)
|
||||
|
||||
private val article1 = Article(
|
||||
content = "Hi",
|
||||
createdBy = tesla,
|
||||
description = "blablabla",
|
||||
title = "Super article"
|
||||
)
|
||||
|
||||
private val choice1 = OpinionChoice(
|
||||
name = "Opinion1",
|
||||
target = listOf()
|
||||
)
|
||||
|
||||
init {
|
||||
mockkStatic("fr.dcproject.security.voter.VoterKt")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `support opinion choice`() = OpinionChoiceVoter().run {
|
||||
val p = object : ActionI {}
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns tesla.user
|
||||
}.let {
|
||||
supports(OpinionChoiceVoter.Action.VIEW, it, choice1) `should be` true
|
||||
supports(OpinionChoiceVoter.Action.VIEW, it, article1) `should be` false
|
||||
supports(p, it, choice1) `should be` false
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can be view the opinion choice`() = listOf(OpinionChoiceVoter()).run {
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns tesla.user
|
||||
}.let {
|
||||
can(OpinionChoiceVoter.Action.VIEW, it, choice1) `should be` true
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can be view the opinion choice list`() = listOf(OpinionChoiceVoter()).run {
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns tesla.user
|
||||
}.let {
|
||||
can(OpinionChoiceVoter.Action.VIEW, it, listOf(choice1)) `should be` true
|
||||
}
|
||||
}
|
||||
}
|
||||
144
src/test/kotlin/fr/dcproject/security/voter/OpinionVoterTest.kt
Normal file
144
src/test/kotlin/fr/dcproject/security/voter/OpinionVoterTest.kt
Normal file
@@ -0,0 +1,144 @@
|
||||
package fr.dcproject.security.voter
|
||||
|
||||
import fr.dcproject.entity.*
|
||||
import io.ktor.application.ApplicationCall
|
||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import io.mockk.mockkStatic
|
||||
import org.amshove.kluent.`should be`
|
||||
import org.joda.time.DateTime
|
||||
import org.junit.jupiter.api.Tag
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
|
||||
@KtorExperimentalLocationsAPI
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
@Tag("voter")
|
||||
internal class OpinionVoterTest {
|
||||
private val tesla = CitizenBasic(
|
||||
user = User(
|
||||
username = "nicolas-tesla",
|
||||
roles = listOf(UserI.Roles.ROLE_USER)
|
||||
),
|
||||
birthday = DateTime.now(),
|
||||
email = "tesla@best.com",
|
||||
name = CitizenI.Name("Nicolas", "Tesla"),
|
||||
followAnonymous = false
|
||||
)
|
||||
|
||||
private val einstein = CitizenBasic(
|
||||
user = User(
|
||||
username = "albert-einstein",
|
||||
roles = listOf(UserI.Roles.ROLE_USER)
|
||||
),
|
||||
birthday = DateTime.now(),
|
||||
email = "einstein@best.com",
|
||||
name = CitizenI.Name("Albert", "Einstein"),
|
||||
followAnonymous = true
|
||||
)
|
||||
|
||||
private val article1 = Article(
|
||||
content = "Hi",
|
||||
createdBy = einstein,
|
||||
description = "blablabla",
|
||||
title = "Super article"
|
||||
)
|
||||
|
||||
private val opinion1 = Opinion(
|
||||
createdBy = tesla,
|
||||
target = article1,
|
||||
choice = OpinionChoice(
|
||||
name = "Opinion1",
|
||||
target = listOf("article")
|
||||
)
|
||||
)
|
||||
|
||||
init {
|
||||
mockkStatic("fr.dcproject.security.voter.VoterKt")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `support opinion`() = OpinionVoter().run {
|
||||
val p = object : ActionI {}
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns tesla.user
|
||||
}.let {
|
||||
supports(OpinionVoter.Action.VIEW, it, opinion1) `should be` true
|
||||
supports(OpinionVoter.Action.VIEW, it, article1) `should be` false
|
||||
supports(p, it, opinion1) `should be` false
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can be view the opinion`() = listOf(OpinionVoter()).run {
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns tesla.user
|
||||
}.let {
|
||||
can(OpinionVoter.Action.VIEW, it, opinion1) `should be` true
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can be not view the opinion if is null`() = listOf(OpinionVoter()).run {
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns tesla.user
|
||||
}.let {
|
||||
can(OpinionVoter.Action.VIEW, it, null) `should be` false
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can be view the opinion list`() = listOf(OpinionVoter()).run {
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns tesla.user
|
||||
}.let {
|
||||
can(OpinionVoter.Action.VIEW, it, listOf(opinion1)) `should be` true
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can be opinion an article`() = listOf(OpinionVoter()).run {
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns tesla.user
|
||||
}.let {
|
||||
can(OpinionVoter.Action.CREATE, it, opinion1) `should be` true
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can not be opinion if not connected`() = listOf(OpinionVoter()).run {
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns null
|
||||
}.let {
|
||||
can(OpinionVoter.Action.CREATE, it, opinion1) `should be` false
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can be remove opinion`() = listOf(OpinionVoter()).run {
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns tesla.user
|
||||
}.let {
|
||||
can(OpinionVoter.Action.DELETE, it, opinion1) `should be` true
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can not be remove opinion if not connected`() = listOf(OpinionVoter()).run {
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns null
|
||||
}.let {
|
||||
can(OpinionVoter.Action.DELETE, it, opinion1) `should be` false
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can not be remove opinion of other user`() = listOf(OpinionVoter()).run {
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns einstein.user
|
||||
}.let {
|
||||
can(OpinionVoter.Action.DELETE, it, opinion1) `should be` false
|
||||
}
|
||||
}
|
||||
}
|
||||
168
src/test/kotlin/fr/dcproject/security/voter/VoteVoterTest.kt
Normal file
168
src/test/kotlin/fr/dcproject/security/voter/VoteVoterTest.kt
Normal file
@@ -0,0 +1,168 @@
|
||||
package fr.dcproject.security.voter
|
||||
|
||||
import fr.dcproject.entity.*
|
||||
import fr.dcproject.entity.Vote as VoteEntity
|
||||
import io.ktor.application.ApplicationCall
|
||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import io.mockk.mockkStatic
|
||||
import org.amshove.kluent.`should be`
|
||||
import org.joda.time.DateTime
|
||||
import org.junit.jupiter.api.Tag
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
|
||||
@KtorExperimentalLocationsAPI
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
@Tag("voter")
|
||||
internal class VoteVoterTest {
|
||||
private val tesla = CitizenBasic(
|
||||
user = User(
|
||||
username = "nicolas-tesla",
|
||||
roles = listOf(UserI.Roles.ROLE_USER)
|
||||
),
|
||||
birthday = DateTime.now(),
|
||||
email = "tesla@best.com",
|
||||
name = CitizenI.Name("Nicolas", "Tesla"),
|
||||
followAnonymous = false
|
||||
)
|
||||
|
||||
private val einstein = CitizenBasic(
|
||||
user = User(
|
||||
username = "albert-einstein",
|
||||
roles = listOf(UserI.Roles.ROLE_USER)
|
||||
),
|
||||
birthday = DateTime.now(),
|
||||
email = "einstein@best.com",
|
||||
name = CitizenI.Name("Albert", "Einstein"),
|
||||
followAnonymous = true
|
||||
)
|
||||
|
||||
private val article1 = Article(
|
||||
content = "Hi",
|
||||
createdBy = einstein,
|
||||
description = "blablabla",
|
||||
title = "Super article"
|
||||
)
|
||||
|
||||
private val vote1 = VoteEntity(
|
||||
createdBy = tesla,
|
||||
target = article1,
|
||||
note = 1
|
||||
)
|
||||
|
||||
private val voteOnDeleted = VoteEntity(
|
||||
createdBy = tesla,
|
||||
target = Article(
|
||||
content = "Hi",
|
||||
createdBy = einstein,
|
||||
description = "blablabla",
|
||||
title = "Super article"
|
||||
).apply { deletedAt = DateTime.now() },
|
||||
note = 1
|
||||
)
|
||||
|
||||
private val voteWithoutUser = VoteEntity(
|
||||
createdBy = tesla,
|
||||
target = ArticleRef(),
|
||||
note = 1
|
||||
)
|
||||
|
||||
init {
|
||||
mockkStatic("fr.dcproject.security.voter.VoterKt")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `support vote`() = VoteVoter().run {
|
||||
val p = object : ActionI {}
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns tesla.user
|
||||
}.let {
|
||||
supports(VoteVoter.Action.VIEW, it, vote1) `should be` true
|
||||
supports(VoteVoter.Action.VIEW, it, article1) `should be` false
|
||||
supports(p, it, vote1) `should be` false
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can be view your the vote`() = listOf(VoteVoter()).run {
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns tesla.user
|
||||
}.let {
|
||||
can(VoteVoter.Action.VIEW, it, vote1) `should be` true
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can not be view vote of other`() = listOf(VoteVoter()).run {
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns einstein.user
|
||||
}.let {
|
||||
can(VoteVoter.Action.VIEW, it, vote1) `should be` false
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can be not view the vote if is null`() = listOf(VoteVoter()).run {
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns tesla.user
|
||||
}.let {
|
||||
can(VoteVoter.Action.VIEW, it, null) `should be` false
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can be view your votes list`() = listOf(VoteVoter()).run {
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns tesla.user
|
||||
}.let {
|
||||
can(VoteVoter.Action.VIEW, it, listOf(vote1)) `should be` true
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can be vote an article`() = listOf(VoteVoter(), ArticleVoter()).run {
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns tesla.user
|
||||
}.let {
|
||||
can(VoteVoter.Action.CREATE, it, vote1) `should be` true
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can not be vote if not connected`() = listOf(VoteVoter()).run {
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns null
|
||||
}.let {
|
||||
can(VoteVoter.Action.CREATE, it, vote1) `should be` false
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can not be vote an article if article is deleted`() = listOf(VoteVoter(), ArticleVoter()).run {
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns tesla.user
|
||||
}.let {
|
||||
can(VoteVoter.Action.CREATE, it, voteOnDeleted) `should be` false
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can not be vote an article if article have no user`() = listOf(VoteVoter(), ArticleVoter()).run {
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns tesla.user
|
||||
}.let {
|
||||
can(VoteVoter.Action.CREATE, it, voteWithoutUser) `should be` false
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can not be comment an article if article is deleted`() = listOf(VoteVoter(), ArticleVoter()).run {
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns tesla.user
|
||||
}.let {
|
||||
can(CommentVoter.Action.CREATE, it, voteOnDeleted) `should be` false
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,204 @@
|
||||
package fr.dcproject.security.voter
|
||||
|
||||
import fr.dcproject.entity.*
|
||||
import io.ktor.application.ApplicationCall
|
||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import io.mockk.mockkStatic
|
||||
import org.amshove.kluent.`should be`
|
||||
import org.joda.time.DateTime
|
||||
import org.junit.jupiter.api.Assertions
|
||||
import org.junit.jupiter.api.Tag
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
import fr.dcproject.entity.Workgroup as WorkgroupEntity
|
||||
|
||||
@KtorExperimentalLocationsAPI
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
@Tag("voter")
|
||||
internal class WorkgroupVoterTest {
|
||||
private val tesla = CitizenBasic(
|
||||
user = User(
|
||||
username = "nicolas-tesla",
|
||||
roles = listOf(UserI.Roles.ROLE_USER)
|
||||
),
|
||||
birthday = DateTime.now(),
|
||||
email = "tesla@best.com",
|
||||
name = CitizenI.Name("Nicolas", "Tesla"),
|
||||
followAnonymous = false
|
||||
)
|
||||
|
||||
private val einstein = CitizenBasic(
|
||||
user = User(
|
||||
username = "albert-einstein",
|
||||
roles = listOf(UserI.Roles.ROLE_USER)
|
||||
),
|
||||
birthday = DateTime.now(),
|
||||
email = "einstein@best.com",
|
||||
name = CitizenI.Name("Albert", "Einstein"),
|
||||
followAnonymous = true
|
||||
)
|
||||
|
||||
private val article1 = Article(
|
||||
content = "Hi",
|
||||
createdBy = einstein,
|
||||
description = "blablabla",
|
||||
title = "Super article"
|
||||
)
|
||||
|
||||
private val workgroupPublic = WorkgroupEntity(
|
||||
createdBy = tesla,
|
||||
description = "Super desc",
|
||||
name = "super name",
|
||||
owner = tesla,
|
||||
anonymous = false
|
||||
)
|
||||
|
||||
private val workgroupAnon = WorkgroupEntity(
|
||||
createdBy = tesla,
|
||||
description = "Super desc",
|
||||
name = "super name",
|
||||
owner = tesla,
|
||||
anonymous = true
|
||||
)
|
||||
|
||||
private val workgroupref = WorkgroupRef()
|
||||
|
||||
init {
|
||||
mockkStatic("fr.dcproject.security.voter.VoterKt")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `support workgroup`() = WorkgroupVoter().run {
|
||||
val p = object : ActionI {}
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns tesla.user
|
||||
}.let {
|
||||
supports(WorkgroupVoter.Action.VIEW, it, workgroupPublic) `should be` true
|
||||
supports(WorkgroupVoter.Action.VIEW, it, article1) `should be` false
|
||||
supports(p, it, workgroupPublic) `should be` false
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can be view your workgroup`() = listOf(WorkgroupVoter()).run {
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns tesla.user
|
||||
}.let {
|
||||
can(WorkgroupVoter.Action.VIEW, it, workgroupPublic) `should be` true
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can be view your workgroup if is not public`() = listOf(WorkgroupVoter()).run {
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns tesla.user
|
||||
}.let {
|
||||
can(WorkgroupVoter.Action.VIEW, it, workgroupAnon) `should be` true
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can be view workgroup of other if is public`() = listOf(WorkgroupVoter()).run {
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns einstein.user
|
||||
}.let {
|
||||
can(WorkgroupVoter.Action.VIEW, it, workgroupPublic) `should be` true
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can not be view workgroup of other if is not public`() = listOf(WorkgroupVoter()).run {
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns einstein.user
|
||||
}.let {
|
||||
can(WorkgroupVoter.Action.VIEW, it, workgroupAnon) `should be` false
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can be not view the workgroup if is null`() = listOf(WorkgroupVoter()).run {
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns tesla.user
|
||||
}.let {
|
||||
can(WorkgroupVoter.Action.VIEW, it, null) `should be` false
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can be view your workgroup list`() = listOf(WorkgroupVoter()).run {
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns tesla.user
|
||||
}.let {
|
||||
can(WorkgroupVoter.Action.VIEW, it, listOf(workgroupPublic)) `should be` true
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can be create workgroup`() = listOf(WorkgroupVoter()).run {
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns tesla.user
|
||||
}.let {
|
||||
can(WorkgroupVoter.Action.CREATE, it, workgroupPublic) `should be` true
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can not be create workgroup if not connected`() = listOf(WorkgroupVoter()).run {
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns null
|
||||
}.let {
|
||||
can(WorkgroupVoter.Action.CREATE, it, workgroupPublic) `should be` false
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can be delete workgroup if owner`() = listOf(WorkgroupVoter()).run {
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns tesla.user
|
||||
}.let {
|
||||
can(WorkgroupVoter.Action.DELETE, it, workgroupPublic) `should be` true
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can not be delete workgroup if not owner`() = listOf(WorkgroupVoter()).run {
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns einstein.user
|
||||
}.let {
|
||||
can(WorkgroupVoter.Action.DELETE, it, workgroupPublic) `should be` false
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can be update workgroup if owner`() = listOf(WorkgroupVoter()).run {
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns tesla.user
|
||||
}.let {
|
||||
can(WorkgroupVoter.Action.UPDATE, it, workgroupPublic) `should be` true
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can not be update workgroup if not owner`() = listOf(WorkgroupVoter()).run {
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns einstein.user
|
||||
}.let {
|
||||
can(WorkgroupVoter.Action.UPDATE, it, workgroupPublic) `should be` false
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can not be update workgroup if workgroup has no user`() {
|
||||
Assertions.assertThrows(VoterException::class.java) {
|
||||
listOf(WorkgroupVoter()).run {
|
||||
mockk<ApplicationCall> {
|
||||
every { user } returns tesla.user
|
||||
}.let {
|
||||
can(WorkgroupVoter.Action.UPDATE, it, workgroupref)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,21 +2,27 @@
|
||||
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 versions of article by the id
|
||||
When I send a GET request to "/articles/9226c1a3-8091-c3fa-7d0d-c2e98c9bee7b/versions"
|
||||
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
|
||||
When I send a GET request to "/articles/9226c1a3-8091-c3fa-7d0d-c2e98c9bee7b"
|
||||
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 | 9226c1a3-8091-c3fa-7d0d-c2e98c9bee7b |
|
||||
| id | 65cda9f3-8991-4420-8d41-1da9da72c9bb |
|
||||
|
||||
Scenario: The route for create article must response a 200 and return object
|
||||
Given I am authenticated as John Doe with id "64b7b379-2298-43ec-b428-ba134930cabd"
|
||||
Given I have citizen John Doe
|
||||
And I am authenticated as John Doe
|
||||
When I send a POST request to "/articles" with body:
|
||||
"""
|
||||
{
|
||||
@@ -27,10 +33,7 @@ Feature: articles routes
|
||||
"description": "description2",
|
||||
"tags": [
|
||||
"green"
|
||||
],
|
||||
"created_by": {
|
||||
"id": "64b7b379-2298-43ec-b428-ba134930cabd"
|
||||
}
|
||||
]
|
||||
}
|
||||
"""
|
||||
Then the response status code should be 200
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
@auth
|
||||
Feature: Auth routes
|
||||
|
||||
Scenario: The route for create citizen must response a 200 and return object
|
||||
@@ -34,10 +35,11 @@ Feature: Auth routes
|
||||
Then the response status code should be 400
|
||||
|
||||
Scenario: 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:
|
||||
"""
|
||||
{
|
||||
"name": "username-1",
|
||||
"name": "niels-bohr",
|
||||
"password": "azerty"
|
||||
}
|
||||
"""
|
||||
|
||||
@@ -1,31 +1,35 @@
|
||||
@citizen
|
||||
Feature: citizens routes
|
||||
|
||||
Scenario: The route for get citizens must response a 200
|
||||
Given I am authenticated as John Doe with id "64b7b379-2298-43ec-b428-ba134930cabd"
|
||||
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: The route for get one citizen must response a 200 and return citizen
|
||||
Given I am authenticated as John Doe with id "64b7b379-2298-43ec-b428-ba134930cabd"
|
||||
When I send a GET request to "/citizens/6434f4f9-f570-f22a-c134-8668350651ff"
|
||||
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 | 6434f4f9-f570-f22a-c134-8668350651ff |
|
||||
| id | 47a05c0f-7329-46c3-a7d0-325db37e9114 |
|
||||
|
||||
Scenario: Can get connected citizen
|
||||
Given I am authenticated as John Doe with id "64b7b379-2298-43ec-b428-ba134930cabd"
|
||||
Given I have citizen Henri Becquerel with ID "47356809-c8ef-4649-8b99-1c5cb9886d38"
|
||||
Given 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 | 64b7b379-2298-43ec-b428-ba134930cabd |
|
||||
| id | 47356809-c8ef-4649-8b99-1c5cb9886d38 |
|
||||
|
||||
@online
|
||||
Scenario: Can be connect with SSO
|
||||
Given I have citizen:
|
||||
Given I have citizen
|
||||
| id | c606110c-ff0e-4d09-a79e-74632d7bf7bd |
|
||||
| firstName | John |
|
||||
| lastName | Doe |
|
||||
| email | fabrice.lecomte.be@gmail.com |
|
||||
| firstName | Leonhard |
|
||||
| lastName | Euler |
|
||||
When I send a POST request to "/sso" with body:
|
||||
"""
|
||||
{
|
||||
@@ -36,8 +40,9 @@ Feature: citizens routes
|
||||
Then the response status code should be 204
|
||||
|
||||
Scenario: Can be change my password
|
||||
Given I am authenticated as Joe Patate with id "c211dca6-aa21-45c2-95ba-c7f2179ee37e"
|
||||
When I send a PUT request to "/citizens/c211dca6-aa21-45c2-95ba-c7f2179ee37e/password/change" with body:
|
||||
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",
|
||||
@@ -47,8 +52,10 @@ Feature: citizens routes
|
||||
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 am authenticated as Joe Carotte with id "19110bb5-58a2-4ef1-9497-0207d4b4f48f"
|
||||
When I send a PUT request to "/citizens/19110bb5-58a2-4ef1-9497-0207d4b4f48f/password/change" with body:
|
||||
|
||||
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",
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
@comment
|
||||
Feature: comment
|
||||
|
||||
Scenario: Can comment childrens
|
||||
Given I am authenticated as John Doe with id "64b7b379-2298-43ec-b428-ba134930cabd"
|
||||
And I have article with id "9226c1a3-8091-c3fa-7d0d-c2e98c9bee7b"
|
||||
When I send a GET request to "/comments/9226c1a3-8091-c3fa-7d0d-c2e98c9bee7b/children"
|
||||
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
|
||||
@@ -1,9 +1,12 @@
|
||||
@comment
|
||||
Feature: comment Article
|
||||
|
||||
Scenario: Can comment an article
|
||||
Given I am authenticated as John Doe with id "64b7b379-2298-43ec-b428-ba134930cabd"
|
||||
And I have article with id "9226c1a3-8091-c3fa-7d0d-c2e98c9bee7b"
|
||||
When I send a POST request to "/articles/9226c1a3-8091-c3fa-7d0d-c2e98c9bee7b/comments" with body:
|
||||
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"
|
||||
@@ -11,32 +14,52 @@ Feature: comment Article
|
||||
"""
|
||||
Then the response status code should be 201
|
||||
|
||||
# TODO add more comment on article
|
||||
Scenario: Can get all comment on article
|
||||
Given I am authenticated as John Doe with id "64b7b379-2298-43ec-b428-ba134930cabd"
|
||||
And I have article with id "9226c1a3-8091-c3fa-7d0d-c2e98c9bee7b"
|
||||
When I send a GET request to "/articles/9226c1a3-8091-c3fa-7d0d-c2e98c9bee7b/comments"
|
||||
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 am authenticated as John Doe with id "64b7b379-2298-43ec-b428-ba134930cabd"
|
||||
And I have article with id "9226c1a3-8091-c3fa-7d0d-c2e98c9bee7b"
|
||||
When I send a GET request to "/articles/9226c1a3-8091-c3fa-7d0d-c2e98c9bee7b/comments?sort=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 Enrico Fermi 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[1].votes.up | 1 |
|
||||
| $.result[0].votes.up | 0 |
|
||||
|
||||
Scenario: Can get comments on articles of the current citizen
|
||||
Given I have citizen John Doe with id "64b7b379-2298-43ec-b428-ba134930cabd"
|
||||
And I have article with id "9226c1a3-8091-c3fa-7d0d-c2e98c9bee7b"
|
||||
When I send a GET request to "/citizens/64b7b379-2298-43ec-b428-ba134930cabd/comments/articles"
|
||||
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 am authenticated as username 3 with id "92877af7-0a45-fd6a-2ed7-fe81e1236b78"
|
||||
When I send a PUT request to "/comments/2f01c257-cf20-3466-fb10-a3b8eff12a97" with body:
|
||||
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
|
||||
"""
|
||||
@@ -45,7 +68,13 @@ Feature: comment Article
|
||||
| content | Hello boy |
|
||||
|
||||
Scenario: Can get comment by its ID
|
||||
When I send a GET request to "/comments/2f01c257-cf20-3466-fb10-a3b8eff12a97"
|
||||
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 |
|
||||
|
||||
@@ -1,35 +1,31 @@
|
||||
@comment
|
||||
Feature: comment Constitution
|
||||
|
||||
Scenario: Can comment an constitution
|
||||
Given I am authenticated as John Toe with id "a6eb1f5a-8c02-42f4-8e8e-a722f26841ef"
|
||||
And I have constitution with id "d7e20f0b-3fdd-4638-817a-bbd87054eb82" created by "john-toe"
|
||||
When I send a POST request to "/constitutions/d7e20f0b-3fdd-4638-817a-bbd87054eb82/comments" with body:
|
||||
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:
|
||||
"""
|
||||
Hello mister
|
||||
{
|
||||
"content": "Hello mister"
|
||||
}
|
||||
"""
|
||||
Then the response status code should be 201
|
||||
|
||||
Scenario: Can get comments on constitution of the current citizen
|
||||
Given I have citizen John Doe with id "64b7b379-2298-43ec-b428-ba134930cabd"
|
||||
And I have constitution with id "9226c1a3-8091-c3fa-7d0d-c2e98c9bee7b"
|
||||
When I send a GET request to "/citizens/64b7b379-2298-43ec-b428-ba134930cabd/comments/constitutions"
|
||||
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 |
|
||||
|
||||
Scenario: Can edit a comment
|
||||
Given I am authenticated as username 3 with id "92877af7-0a45-fd6a-2ed7-fe81e1236b78"
|
||||
When I send a PUT request to "/comments/b0422e48-687f-bea7-b45f-b6b301246e97" with body:
|
||||
And the Response should contain:
|
||||
"""
|
||||
Hello boy
|
||||
34ddd50a-da00-4a90-a869-08baa2a121be
|
||||
"""
|
||||
Then the response status code should be 200
|
||||
And the JSON should contain:
|
||||
| content | Hello boy |
|
||||
|
||||
Scenario: Can get comment by its ID
|
||||
When I send a GET request to "/comments/b0422e48-687f-bea7-b45f-b6b301246e97"
|
||||
Then the response status code should be 200
|
||||
And the JSON should contain:
|
||||
| content | Hello boy |
|
||||
|
||||
@@ -1,17 +1,21 @@
|
||||
Feature: constitution routes
|
||||
@constitution
|
||||
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
|
||||
When I send a GET request to "/constitutions/0ca489a6-ef68-8bd5-2355-5793d4b3d66c"
|
||||
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 | 0ca489a6-ef68-8bd5-2355-5793d4b3d66c |
|
||||
| id | 0321c8d1-4ce3-4763-b5f4-a92611d280b4 |
|
||||
|
||||
Scenario: The route for create constitution must response a 200 and return object
|
||||
Given I am authenticated as John Doe with id "64b7b379-2298-43ec-b428-ba134930cabd"
|
||||
Given I have citizen Henri Poincaré
|
||||
And I am authenticated as Henri Poincaré
|
||||
When I send a POST request to "/constitutions" with body:
|
||||
"""
|
||||
{
|
||||
@@ -20,19 +24,10 @@ Feature: constitution routes
|
||||
"annonymous":true,
|
||||
"titles":[
|
||||
{
|
||||
"id":"8156b66f-a9c8-4fd9-8375-a8a1f42ccfd2",
|
||||
"name":"plop",
|
||||
"rank":0,
|
||||
"created_by":{
|
||||
"id":"64b7b379-2298-43ec-b428-ba134930cabd"
|
||||
}
|
||||
"rank":0
|
||||
}
|
||||
],
|
||||
"created_by":{
|
||||
"id":"64b7b379-2298-43ec-b428-ba134930cabd"
|
||||
},
|
||||
"created_at":null,
|
||||
"version_number":null
|
||||
]
|
||||
}
|
||||
"""
|
||||
Then the response status code should be 200
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
@follow
|
||||
Feature: follow Article and Constitution
|
||||
|
||||
# Article
|
||||
Scenario: The route for follow article must response a 201 and return object
|
||||
Given I am authenticated as John Doe with id "64b7b379-2298-43ec-b428-ba134930cabd"
|
||||
When I send a POST request to "/articles/9226c1a3-8091-c3fa-7d0d-c2e98c9bee7b/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 John Smith with id "e3c0b08c-11be-418e-95e0-8596b4402feb"
|
||||
When I send a GET request to "/citizens/e3c0b08c-11be-418e-95e0-8596b4402feb/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 am authenticated as John Doe with id "64b7b379-2298-43ec-b428-ba134930cabd"
|
||||
When I send a DELETE request to "/articles/9226c1a3-8091-c3fa-7d0d-c2e98c9bee7b/follows"
|
||||
Then the response status code should be 204
|
||||
|
||||
# Constitution
|
||||
Scenario: The route for follow constitution must response a 201 and return object
|
||||
Given I am authenticated as John Doe with id "64b7b379-2298-43ec-b428-ba134930cabd"
|
||||
When I send a POST request to "/constitutions/72aa1ee1-4963-eb44-c9e0-5ce6e0f18f00/follow"
|
||||
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 John Smith with id "e3c0b08c-11be-418e-95e0-8596b4402feb"
|
||||
When I send a GET request to "/citizens/e3c0b08c-11be-418e-95e0-8596b4402feb/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 am authenticated as John Doe with id "64b7b379-2298-43ec-b428-ba134930cabd"
|
||||
When I send a DELETE request to "/constitutions/72aa1ee1-4963-eb44-c9e0-5ce6e0f18f00/follow"
|
||||
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 The citizen Marie Curie follow 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 |
|
||||
42
src/test/resources/feature/followArticle.feature
Normal file
42
src/test/resources/feature/followArticle.feature
Normal file
@@ -0,0 +1,42 @@
|
||||
@follow
|
||||
Feature: follow Article
|
||||
|
||||
# Article
|
||||
Scenario: The route for follow article must response a 201 and return
|
||||
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 |
|
||||
42
src/test/resources/feature/followConstitution.feature
Normal file
42
src/test/resources/feature/followConstitution.feature
Normal file
@@ -0,0 +1,42 @@
|
||||
@follow
|
||||
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 |
|
||||
@@ -1,63 +1,73 @@
|
||||
@opinion
|
||||
Feature: Opinion
|
||||
|
||||
Scenario: Can get one opinion Choices
|
||||
When I send a GET request to "/opinions/6e978eb5-3c48-0def-b093-e01f43983adb"
|
||||
Then the response status code should be 200
|
||||
And the JSON should contain:
|
||||
| name | Opinion1 |
|
||||
|
||||
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:
|
||||
| id | 2f414045-95d9-42ca-a3a9-8cdde52ad253 |
|
||||
| firstName | Isaac |
|
||||
| lastName | Newton |
|
||||
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-c2e98c9bee7 |
|
||||
| createdBy | Isaac Newton |
|
||||
And I have an opinion
|
||||
| opinion | Opinion1 |
|
||||
| article | 9226c1a3-8091-c3fa-7d0d-c2e98c9bee7b |
|
||||
| id | 9226c1a3-8091-c3fa-7d0d-c2e98c9bee7b |
|
||||
| createdBy | Isaac Newton |
|
||||
And I have an opinion choice "Opinion4" with ID "0f4f1721-3136-44f1-9f31-1459f3317b15"
|
||||
And I have an opinion "Opinion4" on article "9226c1a3-8091-c3fa-7d0d-c2e98c9bee7b" created by Isaac Newton with ID "74e93e12-556b-4399-95a6-04f93a4dd66c"
|
||||
When I send a PUT request to "/articles/9226c1a3-8091-c3fa-7d0d-c2e98c9bee7b/opinions" with body:
|
||||
"""
|
||||
{
|
||||
"opinion_choice": "6e978eb5-3c48-0def-b093-e01f43983adb"
|
||||
"opinion_choice": "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
|
||||
When I send a GET request to "/citizens/6434f4f9-f570-f22a-c134-8668350651ff/opinions?id=9226c1a3-8091-c3fa-7d0d-c2e98c9bee7b"
|
||||
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 | Opinion2 |
|
||||
| [0].name | Opinion5 |
|
||||
|
||||
Scenario: Can recieve opinion aggregation with article
|
||||
When I send a GET request to "/articles/9226c1a3-8091-c3fa-7d0d-c2e98c9bee7b"
|
||||
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.Opinion2 | 1 |
|
||||
| opinions.Opinion6 | 1 |
|
||||
| opinions.Opinion7 | 2 |
|
||||
|
||||
Scenario: Can get all opinion of one citizen
|
||||
Given I have citizen:
|
||||
| id | c1542096-3431-432d-8e35-9dc071d4c818 |
|
||||
| firstName | Albert |
|
||||
| lastName | Einstein |
|
||||
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
|
||||
| opinion | Opinion1 |
|
||||
| article | 9226c1a3-8091-c3fa-7d0d-c2e98c9bee7b |
|
||||
| createdBy | 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 | Opinion1 |
|
||||
| result[0].name | Opinion9 |
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
@vote
|
||||
Feature: vote Article
|
||||
|
||||
Scenario: Can Vote article
|
||||
Given I am authenticated as John Doe with id "64b7b379-2298-43ec-b428-ba134930cabd"
|
||||
When I send a PUT request to "/articles/9226c1a3-8091-c3fa-7d0d-c2e98c9bee7b/vote" with body:
|
||||
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
|
||||
@@ -11,8 +14,10 @@ Feature: vote Article
|
||||
Then the response status code should be 201
|
||||
|
||||
Scenario: Can Vote constitution
|
||||
Given I am authenticated as John Doe with id "64b7b379-2298-43ec-b428-ba134930cabd"
|
||||
When I send a PUT request to "/constitutions/64b1f265-bfb3-332b-eef9-d00f63a3beaa/vote" with body:
|
||||
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
|
||||
@@ -21,8 +26,11 @@ Feature: vote Article
|
||||
Then the response status code should be 201
|
||||
|
||||
Scenario: Can get votes of current citizen
|
||||
Given I am authenticated as John Doe with id "64b7b379-2298-43ec-b428-ba134930cabd"
|
||||
When I send a GET request to "/citizens/64b7b379-2298-43ec-b428-ba134930cabd/votes/articles"
|
||||
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 |
|
||||
@@ -31,16 +39,25 @@ Feature: vote Article
|
||||
| result[0].note | 1 |
|
||||
|
||||
Scenario: Can get votes of current citizen by target ids
|
||||
Given I am authenticated as John Doe with id "64b7b379-2298-43ec-b428-ba134930cabd"
|
||||
When I send a GET request to "/citizens/64b7b379-2298-43ec-b428-ba134930cabd/votes?id=9226c1a3-8091-c3fa-7d0d-c2e98c9bee7b&id=64b1f265-bfb3-332b-eef9-d00f63a3beaa"
|
||||
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 |
|
||||
| [0].note | -1 |
|
||||
| [1].note | 1 |
|
||||
|
||||
Scenario: Can vote a comment
|
||||
Given I am authenticated as John Doe with id "64b7b379-2298-43ec-b428-ba134930cabd"
|
||||
And I have comment "ea5c9e87-c99e-4646-a381-2910219e077f" on article "cc9c624e-a27e-42de-af78-ae821c657a68"
|
||||
When I send a PUT request to "/comments/ea5c9e87-c99e-4646-a381-2910219e077f/vote" with body:
|
||||
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
|
||||
|
||||
@@ -45,8 +45,8 @@ Feature: Workgroup
|
||||
|
||||
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 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 |
|
||||
@@ -63,8 +63,8 @@ Feature: Workgroup
|
||||
|
||||
Scenario: Can remove member to workgroup
|
||||
Given I have citizen Heinrich Hertz
|
||||
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 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 |
|
||||
@@ -85,15 +85,15 @@ Feature: Workgroup
|
||||
And the JSON should have 1 items
|
||||
|
||||
Scenario: Can update members on workgroup
|
||||
Given I have citizen John Dalton
|
||||
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 John Dalton
|
||||
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 |
|
||||
| owner | John Dalton |
|
||||
| owner | Leon Foucault |
|
||||
And I have members in workgroup "784fe6bc-7635-4ae2-b080-3a4743b998bf":
|
||||
| be3b0926-8628-4426-804a-75188a6eb315 |
|
||||
| d9671eca-abaf-4b67-9230-3ece700c1ddb |
|
||||
|
||||
@@ -58,15 +58,10 @@ begin
|
||||
-- upsert article
|
||||
select upsert_article(created_article) into created_article;
|
||||
|
||||
|
||||
insert into opinion_choice(id, name, target)
|
||||
values (opinion_choice1_id, 'Opinion1', '{article}');
|
||||
|
||||
insert into opinion_choice(id, name)
|
||||
values (opinion_choice2_id, 'Opinion2');
|
||||
|
||||
insert into opinion_choice(name, target)
|
||||
values ('Opinion3', '{article}');
|
||||
select (h->>'id')::uuid into opinion_choice1_id from upsert_opinion_choice('{"name": "Opinion1", "target":["article"]}') h;
|
||||
assert opinion_choice1_id is not null, 'Opinion choice must be return json with id';
|
||||
select (h->>'id')::uuid into opinion_choice2_id from upsert_opinion_choice('{"name": "Opinion2"}') h;
|
||||
perform upsert_opinion_choice('{"name": "Opinion3", "target":["article"]}') h;
|
||||
|
||||
perform upsert_opinion(
|
||||
resource => json_build_object(
|
||||
|
||||
Reference in New Issue
Block a user