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="MAIN_CLASS_NAME" value="" />
|
||||||
<option name="METHOD_NAME" value="" />
|
<option name="METHOD_NAME" value="" />
|
||||||
<option name="TEST_OBJECT" value="package" />
|
<option name="TEST_OBJECT" value="package" />
|
||||||
|
<option name="VM_PARAMETERS" value="-ea -Djdk.attach.allowAttachSelf=true" />
|
||||||
<option name="PARAMETERS" value="" />
|
<option name="PARAMETERS" value="" />
|
||||||
<option name="TEST_SEARCH_SCOPE">
|
<option name="TEST_SEARCH_SCOPE">
|
||||||
<value defaultName="wholeProject" />
|
<value defaultName="wholeProject" />
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<option name="MAIN_CLASS_NAME" value="" />
|
<option name="MAIN_CLASS_NAME" value="" />
|
||||||
<option name="METHOD_NAME" value="" />
|
<option name="METHOD_NAME" value="" />
|
||||||
<option name="TEST_OBJECT" value="tags" />
|
<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="PARAMETERS" value="" />
|
||||||
<option name="TEST_SEARCH_SCOPE">
|
<option name="TEST_SEARCH_SCOPE">
|
||||||
<value defaultName="wholeProject" />
|
<value defaultName="wholeProject" />
|
||||||
|
|||||||
2
.idea/runConfigurations/Article_Tests.xml
generated
2
.idea/runConfigurations/Article_Tests.xml
generated
@@ -1,5 +1,5 @@
|
|||||||
<component name="ProjectRunConfigurationManager">
|
<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" />
|
<output_file path="$PROJECT_DIR$/var/log/test/out.log" is_save="true" />
|
||||||
<module name="dcproject.test" />
|
<module name="dcproject.test" />
|
||||||
<useClassPathOnly />
|
<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">
|
<configuration default="false" name="Cucumber Tests" type="JUnit" factoryName="JUnit">
|
||||||
<output_file path="$PROJECT_DIR$/var/log/test/cucumber.out.log" />
|
<output_file path="$PROJECT_DIR$/var/log/test/cucumber.out.log" />
|
||||||
<module name="dcproject.test" />
|
<module name="dcproject.test" />
|
||||||
|
<useClassPathOnly />
|
||||||
<option name="PACKAGE_NAME" value="" />
|
<option name="PACKAGE_NAME" value="" />
|
||||||
<option name="MAIN_CLASS_NAME" value="RunCucumberTest" />
|
<option name="MAIN_CLASS_NAME" value="RunCucumberTest" />
|
||||||
<option name="METHOD_NAME" value="" />
|
<option name="METHOD_NAME" value="" />
|
||||||
<option name="TEST_OBJECT" value="class" />
|
<option name="TEST_OBJECT" value="class" />
|
||||||
|
<option name="VM_PARAMETERS" value="-ea -Djdk.attach.allowAttachSelf=true" />
|
||||||
<option name="PARAMETERS" value="" />
|
<option name="PARAMETERS" value="" />
|
||||||
<envs>
|
<envs>
|
||||||
<env name="SEND_GRID_KEY" value="$SEND_GRID_KEY$" />
|
<env name="SEND_GRID_KEY" value="$SEND_GRID_KEY$" />
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<component name="ProjectRunConfigurationManager">
|
<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" />
|
<output_file path="$PROJECT_DIR$/var/log/test/out.log" is_save="true" />
|
||||||
<module name="dcproject.test" />
|
<module name="dcproject.test" />
|
||||||
<useClassPathOnly />
|
<useClassPathOnly />
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
<option name="MAIN_CLASS_NAME" value="RunCucumberTest" />
|
<option name="MAIN_CLASS_NAME" value="RunCucumberTest" />
|
||||||
<option name="METHOD_NAME" value="" />
|
<option name="METHOD_NAME" value="" />
|
||||||
<option name="TEST_OBJECT" value="class" />
|
<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="PARAMETERS" value="" />
|
||||||
<option name="TEST_SEARCH_SCOPE">
|
<option name="TEST_SEARCH_SCOPE">
|
||||||
<value defaultName="wholeProject" />
|
<value defaultName="wholeProject" />
|
||||||
4
.idea/runConfigurations/Follow_Tests.xml
generated
4
.idea/runConfigurations/Follow_Tests.xml
generated
@@ -1,5 +1,5 @@
|
|||||||
<component name="ProjectRunConfigurationManager">
|
<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" />
|
<output_file path="$PROJECT_DIR$/var/log/test/out.log" is_save="true" />
|
||||||
<module name="dcproject.test" />
|
<module name="dcproject.test" />
|
||||||
<useClassPathOnly />
|
<useClassPathOnly />
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
<option name="MAIN_CLASS_NAME" value="RunCucumberTest" />
|
<option name="MAIN_CLASS_NAME" value="RunCucumberTest" />
|
||||||
<option name="METHOD_NAME" value="" />
|
<option name="METHOD_NAME" value="" />
|
||||||
<option name="TEST_OBJECT" value="class" />
|
<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="PARAMETERS" value="" />
|
||||||
<option name="TEST_SEARCH_SCOPE">
|
<option name="TEST_SEARCH_SCOPE">
|
||||||
<value defaultName="wholeProject" />
|
<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">
|
<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" />
|
<output_file path="$PROJECT_DIR$/var/log/test/out.log" is_save="true" />
|
||||||
<module name="dcproject.test" />
|
<module name="dcproject.test" />
|
||||||
<useClassPathOnly />
|
<useClassPathOnly />
|
||||||
|
|||||||
4
.idea/runConfigurations/Opinion_Tests.xml
generated
4
.idea/runConfigurations/Opinion_Tests.xml
generated
@@ -1,5 +1,5 @@
|
|||||||
<component name="ProjectRunConfigurationManager">
|
<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" />
|
<output_file path="$PROJECT_DIR$/var/log/test/out.log" is_save="true" />
|
||||||
<module name="dcproject.test" />
|
<module name="dcproject.test" />
|
||||||
<useClassPathOnly />
|
<useClassPathOnly />
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
<option name="MAIN_CLASS_NAME" value="RunCucumberTest" />
|
<option name="MAIN_CLASS_NAME" value="RunCucumberTest" />
|
||||||
<option name="METHOD_NAME" value="" />
|
<option name="METHOD_NAME" value="" />
|
||||||
<option name="TEST_OBJECT" value="class" />
|
<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="PARAMETERS" value="" />
|
||||||
<option name="TEST_SEARCH_SCOPE">
|
<option name="TEST_SEARCH_SCOPE">
|
||||||
<value defaultName="wholeProject" />
|
<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">
|
<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_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.sql" />
|
||||||
<script-file value="$PROJECT_DIR$/src/main/resources/sql/functions/article/find_articles_versions_by_id.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_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/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.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_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/find_workgroups.sql" />
|
||||||
<script-file value="$PROJECT_DIR$/src/main/resources/sql/functions/workgroup/upsert_workgroup.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/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/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/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-file value="$PROJECT_DIR$/src/test/sql/opinion.sql" />
|
||||||
<script-mode>FILE</script-mode>
|
<script-mode>FILE</script-mode>
|
||||||
<data-source id="a9a6d0e9-327d-4e7d-9b93-3cb6f7948866" namespace="database/"test"/schema/"public"" />
|
<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">
|
<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" />
|
<output_file path="$PROJECT_DIR$/var/log/test/out.log" is_save="true" />
|
||||||
<module name="dcproject.test" />
|
<module name="dcproject.test" />
|
||||||
<useClassPathOnly />
|
<useClassPathOnly />
|
||||||
@@ -25,7 +25,6 @@
|
|||||||
<tag value="!online" />
|
<tag value="!online" />
|
||||||
<method v="2">
|
<method v="2">
|
||||||
<option name="Make" enabled="true" />
|
<option name="Make" enabled="true" />
|
||||||
<option name="RunConfigurationTask" enabled="true" run_configuration_name="Test Workgroup" run_configuration_type="DatabaseScript" />
|
|
||||||
</method>
|
</method>
|
||||||
</configuration>
|
</configuration>
|
||||||
</component>
|
</component>
|
||||||
@@ -8,7 +8,7 @@ import fr.postgresjson.entity.mutable.EntityDeletedAtImp
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class OpinionChoice(
|
class OpinionChoice(
|
||||||
id: UUID,
|
id: UUID? = null,
|
||||||
val name: String,
|
val name: String,
|
||||||
val target: List<String>?
|
val target: List<String>?
|
||||||
) : OpinionChoiceRef(id),
|
) : OpinionChoiceRef(id),
|
||||||
@@ -16,5 +16,5 @@ class OpinionChoice(
|
|||||||
EntityDeletedAt by EntityDeletedAtImp()
|
EntityDeletedAt by EntityDeletedAtImp()
|
||||||
|
|
||||||
open class OpinionChoiceRef(
|
open class OpinionChoiceRef(
|
||||||
id: UUID
|
id: UUID?
|
||||||
) : UuidEntity(id)
|
) : UuidEntity(id ?: UUID.randomUUID())
|
||||||
@@ -6,7 +6,7 @@ import fr.postgresjson.entity.mutable.EntityDeletedAtImp
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class Workgroup(
|
class Workgroup(
|
||||||
id: UUID?,
|
id: UUID? = null,
|
||||||
name: String,
|
name: String,
|
||||||
description: String,
|
description: String,
|
||||||
logo: String? = null,
|
logo: String? = null,
|
||||||
@@ -28,7 +28,7 @@ class Workgroup(
|
|||||||
EntityUpdatedAt by EntityUpdatedAtImp()
|
EntityUpdatedAt by EntityUpdatedAtImp()
|
||||||
|
|
||||||
open class WorkgroupSimple<Z : CitizenRef>(
|
open class WorkgroupSimple<Z : CitizenRef>(
|
||||||
id: UUID?,
|
id: UUID? = null,
|
||||||
var name: String,
|
var name: String,
|
||||||
var description: String,
|
var description: String,
|
||||||
var logo: String? = null,
|
var logo: String? = null,
|
||||||
@@ -40,7 +40,7 @@ open class WorkgroupSimple<Z : CitizenRef>(
|
|||||||
EntityDeletedAt by EntityDeletedAtImp()
|
EntityDeletedAt by EntityDeletedAtImp()
|
||||||
|
|
||||||
open class WorkgroupRef(
|
open class WorkgroupRef(
|
||||||
id: UUID?
|
id: UUID? = null
|
||||||
) : UuidEntity(id ?: UUID.randomUUID()), WorkgroupI
|
) : UuidEntity(id ?: UUID.randomUUID()), WorkgroupI
|
||||||
|
|
||||||
interface WorkgroupWithAuthI<Z : CitizenWithUserI> : WorkgroupWithMembersI<Z>, EntityCreatedBy<Z>, EntityDeletedAt {
|
interface WorkgroupWithAuthI<Z : CitizenWithUserI> : WorkgroupWithMembersI<Z>, EntityCreatedBy<Z>, EntityDeletedAt {
|
||||||
|
|||||||
@@ -43,6 +43,12 @@ open class OpinionChoice(override val requester: Requester) : RepositoryI {
|
|||||||
.selectOne(
|
.selectOne(
|
||||||
"id" to id
|
"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) {
|
open class Opinion<T : TargetRef>(requester: Requester) : OpinionChoice(requester) {
|
||||||
|
|||||||
@@ -34,9 +34,6 @@ object ConstitutionPaths {
|
|||||||
@Location("/constitutions/{constitution}")
|
@Location("/constitutions/{constitution}")
|
||||||
class ConstitutionRequest(val constitution: ConstitutionEntity)
|
class ConstitutionRequest(val constitution: ConstitutionEntity)
|
||||||
|
|
||||||
@Location("/constitutions/{constitution}/follow")
|
|
||||||
class ConstitutionFollowRequest(val constitution: ConstitutionEntity)
|
|
||||||
|
|
||||||
@Location("/constitutions")
|
@Location("/constitutions")
|
||||||
class PostConstitutionRequest
|
class PostConstitutionRequest
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import fr.dcproject.repository.FollowConstitution as FollowConstitutionRepositor
|
|||||||
|
|
||||||
@KtorExperimentalLocationsAPI
|
@KtorExperimentalLocationsAPI
|
||||||
object FollowConstitutionPaths {
|
object FollowConstitutionPaths {
|
||||||
@Location("/constitutions/{constitution}/follow")
|
@Location("/constitutions/{constitution}/follows")
|
||||||
class ConstitutionFollowRequest(val constitution: ConstitutionRef)
|
class ConstitutionFollowRequest(val constitution: ConstitutionRef)
|
||||||
|
|
||||||
@Location("/citizens/{citizen}/follows/constitutions")
|
@Location("/citizens/{citizen}/follows/constitutions")
|
||||||
@@ -38,6 +38,13 @@ fun Route.followConstitution(repo: FollowConstitutionRepository) {
|
|||||||
call.respond(HttpStatusCode.NoContent)
|
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> {
|
get<FollowConstitutionPaths.CitizenFollowConstitutionRequest> {
|
||||||
val follows = repo.findByCitizen(it.citizen)
|
val follows = repo.findByCitizen(it.citizen)
|
||||||
assertCan(VIEW, follows.result)
|
assertCan(VIEW, follows.result)
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package fr.dcproject.security.voter
|
|||||||
|
|
||||||
import fr.dcproject.entity.ArticleAuthI
|
import fr.dcproject.entity.ArticleAuthI
|
||||||
import fr.dcproject.entity.ArticleI
|
import fr.dcproject.entity.ArticleI
|
||||||
import fr.dcproject.entity.ArticleSimpleI
|
|
||||||
import fr.dcproject.entity.UserI
|
import fr.dcproject.entity.UserI
|
||||||
import io.ktor.application.ApplicationCall
|
import io.ktor.application.ApplicationCall
|
||||||
import fr.dcproject.entity.Comment as CommentEntity
|
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.VIEW) return view(subject, user)
|
||||||
if (action == Action.DELETE) return delete(subject, user)
|
if (action == Action.DELETE) return delete(subject, user)
|
||||||
if (action == Action.UPDATE) return update(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 VoteVoter.Action) return voteForVote(action, subject)
|
||||||
if (action is Action) return Vote.DENIED
|
if (action is Action) return Vote.DENIED
|
||||||
|
|
||||||
@@ -67,23 +66,36 @@ class ArticleVoter : Voter {
|
|||||||
private fun voteForVote(action: VoteVoter.Action, subject: Any?): Vote {
|
private fun voteForVote(action: VoteVoter.Action, subject: Any?): Vote {
|
||||||
if (action == VoteVoter.Action.CREATE && subject is VoteEntity<*>) {
|
if (action == VoteVoter.Action.CREATE && subject is VoteEntity<*>) {
|
||||||
val target = subject.target
|
val target = subject.target
|
||||||
if (target !is ArticleSimpleI) {
|
if (target is ArticleAuthI<*>) {
|
||||||
return Vote.ABSTAIN
|
if (target.isDeleted()) {
|
||||||
}
|
return Vote.DENIED
|
||||||
if (target.isDeleted()) {
|
}
|
||||||
|
} else if (target is ArticleI) {
|
||||||
return Vote.DENIED
|
return Vote.DENIED
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Vote.ABSTAIN
|
return Vote.ABSTAIN
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun voteForComment(action: CommentVoter.Action): Vote {
|
private fun voteForComment(action: CommentVoter.Action, subject: Any?): Vote {
|
||||||
if (action == CommentVoter.Action.CREATE) {
|
if (subject is CommentEntity<*>) {
|
||||||
return Vote.GRANTED
|
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) {
|
if (action == CommentVoter.Action.VIEW) {
|
||||||
return Vote.GRANTED
|
return Vote.GRANTED
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return Vote.DENIED
|
||||||
}
|
}
|
||||||
|
|
||||||
return Vote.ABSTAIN
|
return Vote.ABSTAIN
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ class CitizenVoter : Voter {
|
|||||||
|
|
||||||
override fun supports(action: ActionI, call: ApplicationCall, subject: Any?): Boolean {
|
override fun supports(action: ActionI, call: ApplicationCall, subject: Any?): Boolean {
|
||||||
return (action is Action)
|
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 {
|
override fun vote(action: ActionI, call: ApplicationCall, subject: Any?): Vote {
|
||||||
@@ -32,14 +32,6 @@ class CitizenVoter : Voter {
|
|||||||
return if (subject.isDeleted()) Vote.DENIED
|
return if (subject.isDeleted()) Vote.DENIED
|
||||||
else Vote.GRANTED
|
else Vote.GRANTED
|
||||||
}
|
}
|
||||||
if (subject is List<*>) {
|
|
||||||
subject.forEach {
|
|
||||||
if (it !is CitizenBasicI || it.isDeleted()) {
|
|
||||||
return Vote.DENIED
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Vote.GRANTED
|
|
||||||
}
|
|
||||||
return Vote.DENIED
|
return Vote.DENIED
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,32 +13,32 @@ class CommentVoter : Voter {
|
|||||||
|
|
||||||
override fun supports(action: ActionI, call: ApplicationCall, subject: Any?): Boolean {
|
override fun supports(action: ActionI, call: ApplicationCall, subject: Any?): Boolean {
|
||||||
return (action is Action)
|
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 {
|
override fun vote(action: ActionI, call: ApplicationCall, subject: Any?): Vote {
|
||||||
val user = call.user
|
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
|
return Vote.GRANTED
|
||||||
}
|
}
|
||||||
|
|
||||||
if (action == Action.VIEW) {
|
if (action == Action.VIEW) {
|
||||||
if (subject is Comment<*>) {
|
return if (subject.isDeleted()) Vote.DENIED
|
||||||
return if (subject.isDeleted()) Vote.DENIED
|
else Vote.GRANTED
|
||||||
else Vote.GRANTED
|
|
||||||
}
|
|
||||||
if (subject is List<*>) {
|
|
||||||
subject.forEach {
|
|
||||||
if (it !is Comment<*> || it.isDeleted()) {
|
|
||||||
return Vote.DENIED
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Vote.GRANTED
|
|
||||||
}
|
|
||||||
return Vote.DENIED
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
return Vote.GRANTED
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ class ConstitutionVoter : Voter {
|
|||||||
|
|
||||||
override fun supports(action: ActionI, call: ApplicationCall, subject: Any?): Boolean {
|
override fun supports(action: ActionI, call: ApplicationCall, subject: Any?): Boolean {
|
||||||
return (action is Action || action is CommentVoter.Action || action is VoteVoter.Action)
|
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 {
|
override fun vote(action: ActionI, call: ApplicationCall, subject: Any?): Vote {
|
||||||
@@ -30,14 +30,6 @@ class ConstitutionVoter : Voter {
|
|||||||
return if (subject.isDeleted()) Vote.DENIED
|
return if (subject.isDeleted()) Vote.DENIED
|
||||||
else Vote.GRANTED
|
else Vote.GRANTED
|
||||||
}
|
}
|
||||||
if (subject is List<*>) {
|
|
||||||
subject.forEach {
|
|
||||||
if (it !is ConstitutionSimple<*, *> || it.isDeleted()) {
|
|
||||||
return Vote.DENIED
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Vote.GRANTED
|
|
||||||
}
|
|
||||||
return Vote.DENIED
|
return Vote.DENIED
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ class FollowVoter : Voter {
|
|||||||
|
|
||||||
override fun supports(action: ActionI, call: ApplicationCall, subject: Any?): Boolean {
|
override fun supports(action: ActionI, call: ApplicationCall, subject: Any?): Boolean {
|
||||||
return (action is Action)
|
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 {
|
override fun vote(action: ActionI, call: ApplicationCall, subject: Any?): Vote {
|
||||||
@@ -32,14 +32,6 @@ class FollowVoter : Voter {
|
|||||||
if (subject is FollowEntity<*>) {
|
if (subject is FollowEntity<*>) {
|
||||||
return voteView(user, subject)
|
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
|
return Vote.DENIED
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ class OpinionChoiceVoter : Voter {
|
|||||||
|
|
||||||
override fun supports(action: ActionI, call: ApplicationCall, subject: Any?): Boolean {
|
override fun supports(action: ActionI, call: ApplicationCall, subject: Any?): Boolean {
|
||||||
return (action is Action)
|
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 {
|
override fun vote(action: ActionI, call: ApplicationCall, subject: Any?): Vote {
|
||||||
@@ -18,14 +18,6 @@ class OpinionChoiceVoter : Voter {
|
|||||||
if (subject is OpinionChoice) {
|
if (subject is OpinionChoice) {
|
||||||
return Vote.GRANTED
|
return Vote.GRANTED
|
||||||
}
|
}
|
||||||
if (subject is List<*>) {
|
|
||||||
subject.forEach {
|
|
||||||
if (it !is OpinionChoice) {
|
|
||||||
return Vote.DENIED
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Vote.GRANTED
|
|
||||||
}
|
|
||||||
return Vote.DENIED
|
return Vote.DENIED
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ class OpinionVoter : Voter {
|
|||||||
|
|
||||||
override fun supports(action: ActionI, call: ApplicationCall, subject: Any?): Boolean {
|
override fun supports(action: ActionI, call: ApplicationCall, subject: Any?): Boolean {
|
||||||
return (action is Action)
|
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 {
|
override fun vote(action: ActionI, call: ApplicationCall, subject: Any?): Vote {
|
||||||
@@ -25,14 +25,6 @@ class OpinionVoter : Voter {
|
|||||||
if (subject is Opinion<*>) {
|
if (subject is Opinion<*>) {
|
||||||
return Vote.GRANTED
|
return Vote.GRANTED
|
||||||
}
|
}
|
||||||
if (subject is List<*>) {
|
|
||||||
subject.forEach {
|
|
||||||
if (it !is Opinion<*>) {
|
|
||||||
return Vote.DENIED
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Vote.GRANTED
|
|
||||||
}
|
|
||||||
return Vote.DENIED
|
return Vote.DENIED
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,10 +37,6 @@ class OpinionVoter : Voter {
|
|||||||
else Vote.DENIED
|
else Vote.DENIED
|
||||||
}
|
}
|
||||||
|
|
||||||
if (action is Action) {
|
|
||||||
return Vote.DENIED
|
|
||||||
}
|
|
||||||
|
|
||||||
return Vote.ABSTAIN
|
return Vote.ABSTAIN
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,10 +10,7 @@ class VoteVoter : Voter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun supports(action: ActionI, call: ApplicationCall, subject: Any?): Boolean {
|
override fun supports(action: ActionI, call: ApplicationCall, subject: Any?): Boolean {
|
||||||
return action is Action && (
|
return action is Action && subject is VoteEntity<*>?
|
||||||
subject is VoteEntity<*>? ||
|
|
||||||
subject is List<*>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun vote(action: ActionI, call: ApplicationCall, subject: Any?): Vote {
|
override fun vote(action: ActionI, call: ApplicationCall, subject: Any?): Vote {
|
||||||
@@ -30,16 +27,6 @@ class VoteVoter : Voter {
|
|||||||
Vote.GRANTED
|
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
|
return Vote.DENIED
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ class WorkgroupVoter : Voter {
|
|||||||
|
|
||||||
override fun supports(action: ActionI, call: ApplicationCall, subject: Any?): Boolean {
|
override fun supports(action: ActionI, call: ApplicationCall, subject: Any?): Boolean {
|
||||||
return (action is Action)
|
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 {
|
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 if (subject.anonymous && user != null && subject.isMember(user)) Vote.GRANTED
|
||||||
else Vote.DENIED
|
else Vote.DENIED
|
||||||
}
|
}
|
||||||
if (subject is List<*>) {
|
|
||||||
subject.forEach {
|
|
||||||
if (it !is WorkgroupWithAuthI<*> || it.isDeleted()) {
|
|
||||||
return Vote.DENIED
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Vote.GRANTED
|
|
||||||
}
|
|
||||||
return Vote.DENIED
|
return Vote.DENIED
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,10 +44,9 @@ class WorkgroupVoter : Voter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return Vote.DENIED
|
return Vote.DENIED
|
||||||
}
|
} else if (subject !is WorkgroupWithAuthI<*> && (action == Action.DELETE || action == Action.UPDATE)) {
|
||||||
|
throw object :
|
||||||
if (action is Action) {
|
VoterException("Unable to define if your are granted, the subject must implement 'WorkgroupWithAuthI'") {}
|
||||||
return Vote.DENIED
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Vote.ABSTAIN
|
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",
|
"username":"jaque",
|
||||||
"blocked_at":null,
|
"blocked_at":null,
|
||||||
"plain_password":"azerty",
|
"plain_password":"azerty",
|
||||||
"created_at":null,
|
"created_at":"2019-08-09T11:42:47.168Z",
|
||||||
"updated_at":null
|
"updated_at":"2019-08-09T11:42:47.168Z"
|
||||||
},
|
},
|
||||||
"created_at":null
|
"created_at":"2019-08-09T11:42:47.168Z"
|
||||||
},
|
},
|
||||||
"target":{
|
"target":{
|
||||||
"id":"34588ea7-c180-4694-801b-1b5c5a6ed73f",
|
"id":"34588ea7-c180-4694-801b-1b5c5a6ed73f",
|
||||||
@@ -66,15 +66,15 @@ class FollowTest {
|
|||||||
"username":"jaque",
|
"username":"jaque",
|
||||||
"blocked_at":null,
|
"blocked_at":null,
|
||||||
"plain_password":"azerty",
|
"plain_password":"azerty",
|
||||||
"created_at":null,
|
"created_at":"2019-08-09T11:42:47.168Z",
|
||||||
"updated_at":null
|
"updated_at":"2019-08-09T11:42:47.168Z"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"version_id":"a4aa7dd4-d174-42d2-9ba5-ae6f1129ffce",
|
"version_id":"a4aa7dd4-d174-42d2-9ba5-ae6f1129ffce",
|
||||||
"version_number":null,
|
"version_number":null,
|
||||||
"created_at":null
|
"created_at":null
|
||||||
},
|
},
|
||||||
"created_at":null
|
"created_at":"2019-08-09T11:42:47.168Z"
|
||||||
}""".trimIndent()
|
}""".trimIndent()
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -42,7 +42,6 @@ class RunCucumberTest : En, KoinTest {
|
|||||||
|
|
||||||
withTestApplication({ module(CUCUMBER) }) {
|
withTestApplication({ module(CUCUMBER) }) {
|
||||||
migrations()
|
migrations()
|
||||||
fixtures()
|
|
||||||
}
|
}
|
||||||
unitialized = true
|
unitialized = true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,12 +72,12 @@ class VoteTest {
|
|||||||
"blocked_at": null,
|
"blocked_at": null,
|
||||||
"plain_password": "azerty",
|
"plain_password": "azerty",
|
||||||
"roles": [],
|
"roles": [],
|
||||||
"created_at": null,
|
"created_at": "2019-08-09T11:42:47.168Z",
|
||||||
"updated_at": null
|
"updated_at": "2019-08-09T11:42:47.168Z"
|
||||||
},
|
},
|
||||||
"deleted": false,
|
"deleted": false,
|
||||||
"created_at": null,
|
"created_at": "2019-08-09T11:42:47.168Z",
|
||||||
"deleted_at": null
|
"deleted_at": "2019-08-09T11:42:47.168Z"
|
||||||
},
|
},
|
||||||
"votes": {
|
"votes": {
|
||||||
"up": 0,
|
"up": 0,
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import org.joda.time.DateTime
|
|||||||
import org.koin.test.KoinTest
|
import org.koin.test.KoinTest
|
||||||
import org.koin.test.get
|
import org.koin.test.get
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.concurrent.CompletionException
|
|
||||||
import fr.dcproject.entity.Article as ArticleEntity
|
import fr.dcproject.entity.Article as ArticleEntity
|
||||||
import fr.dcproject.entity.Comment as CommentEntity
|
import fr.dcproject.entity.Comment as CommentEntity
|
||||||
import fr.dcproject.entity.User as UserEntity
|
import fr.dcproject.entity.User as UserEntity
|
||||||
@@ -18,93 +17,77 @@ import fr.dcproject.repository.Citizen as CitizenRepository
|
|||||||
|
|
||||||
class ArticleSteps : En, KoinTest {
|
class ArticleSteps : En, KoinTest {
|
||||||
init {
|
init {
|
||||||
/**
|
Given("I have {int} article") { nb: Int ->
|
||||||
* @deprecated
|
repeat(nb) {
|
||||||
*/
|
createArticle()
|
||||||
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 article with id {string} created by {string}") { id: String, username: String ->
|
Given("I have article") { extraData: DataTable? ->
|
||||||
val citizen = get<CitizenRepository>().findByUsername(username)!!
|
createArticle(extraData)
|
||||||
|
|
||||||
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 comment {string} on article {string}") { commentId: String, articleId: String ->
|
Given("I have article with ID {string}") { id: String ->
|
||||||
var citizen = Citizen(
|
createArticle(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 {
|
Given("I have comment created by {word} {word} on article {string}:") { firstName: String, lastName: String, articleId: String, extraData: DataTable? ->
|
||||||
get<CitizenRepository>().insertWithUser(citizen)
|
commentArticle(articleId, firstName, lastName, extraData)
|
||||||
} catch (e: CompletionException) {
|
}
|
||||||
citizen = get<CitizenRepository>().findByUsername("john-doe")!!
|
Given("I have comment created by {word} {word} on article {string}") { firstName: String, lastName: String, articleId: String ->
|
||||||
}
|
commentArticle(articleId, firstName, lastName)
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
package feature
|
||||||
|
|
||||||
import fr.dcproject.entity.*
|
import fr.dcproject.entity.*
|
||||||
import fr.dcproject.entity.ConstitutionSimple.TitleSimple
|
import fr.dcproject.repository.CommentConstitution
|
||||||
import fr.dcproject.entity.request.Constitution
|
import fr.dcproject.utils.toUUID
|
||||||
|
import io.cucumber.datatable.DataTable
|
||||||
import io.cucumber.java8.En
|
import io.cucumber.java8.En
|
||||||
import org.joda.time.DateTime
|
import org.joda.time.DateTime
|
||||||
import org.koin.test.KoinTest
|
import org.koin.test.KoinTest
|
||||||
import org.koin.test.get
|
import org.koin.test.get
|
||||||
import java.util.*
|
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.entity.User as UserEntity
|
||||||
import fr.dcproject.repository.Citizen as CitizenRepository
|
import fr.dcproject.repository.Citizen as CitizenRepository
|
||||||
import fr.dcproject.repository.Constitution as ConstitutionRepository
|
import fr.dcproject.repository.Constitution as ConstitutionRepository
|
||||||
|
|
||||||
class ConstitutionSteps : En, KoinTest {
|
class ConstitutionSteps : En, KoinTest {
|
||||||
init {
|
init {
|
||||||
Given("I have constitution with id {string}") { id: String ->
|
Given("I have {int} constitution") { nb: Int ->
|
||||||
var citizen = Citizen(
|
repeat(nb) {
|
||||||
id = UUID.fromString(id),
|
createConstitution()
|
||||||
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 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 ->
|
Given("I have constitution") { extraData: DataTable? ->
|
||||||
val citizen = get<CitizenRepository>().findByUsername(username)!!
|
createConstitution(extraData)
|
||||||
|
}
|
||||||
|
|
||||||
val title1 = TitleSimple<ArticleRef>(
|
Given("I have constitution with ID {string}") { id: String? ->
|
||||||
name = "My Title"
|
createConstitution(id = UUID.fromString(id))
|
||||||
)
|
}
|
||||||
|
|
||||||
val constitution = ConstitutionSimple<CitizenSimple, TitleSimple<ArticleRef>>(
|
Given("I have comment created by {word} {word} on constitution {string}:") { firstName: String, lastName: String, constitutionId: String, extraData: DataTable? ->
|
||||||
id = UUID.fromString(id),
|
commentConstitution(constitutionId, firstName, lastName, extraData)
|
||||||
title = "hello",
|
}
|
||||||
titles = mutableListOf(title1),
|
Given("I have comment created by {word} {word} on constitution {string}") { firstName: String, lastName: String, constitutionId: String ->
|
||||||
anonymous = false,
|
commentConstitution(constitutionId, firstName, lastName)
|
||||||
createdBy = citizen
|
|
||||||
)
|
|
||||||
get<ConstitutionRepository>().upsert(constitution)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
package feature
|
||||||
|
|
||||||
import fr.dcproject.entity.ArticleRef
|
import fr.dcproject.entity.ArticleRef
|
||||||
|
import fr.dcproject.entity.ConstitutionRef
|
||||||
import fr.dcproject.entity.Follow
|
import fr.dcproject.entity.Follow
|
||||||
import fr.dcproject.utils.toUUID
|
import fr.dcproject.utils.toUUID
|
||||||
import io.cucumber.java8.En
|
import io.cucumber.java8.En
|
||||||
@@ -8,14 +9,21 @@ import org.koin.test.KoinTest
|
|||||||
import org.koin.test.get
|
import org.koin.test.get
|
||||||
import fr.dcproject.repository.Citizen as CitizenRepository
|
import fr.dcproject.repository.Citizen as CitizenRepository
|
||||||
import fr.dcproject.repository.FollowArticle as FollowArticleRepository
|
import fr.dcproject.repository.FollowArticle as FollowArticleRepository
|
||||||
|
import fr.dcproject.repository.FollowConstitution as FollowConstitutionRepository
|
||||||
|
|
||||||
class FollowSteps : En, KoinTest {
|
class FollowSteps : En, KoinTest {
|
||||||
init {
|
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 username = "$firstName-$lastName".toLowerCase()
|
||||||
val citizen = get<CitizenRepository>().findByUsername(username) ?: error("Citizen not exist")
|
val citizen = get<CitizenRepository>().findByUsername(username) ?: error("Citizen not exist")
|
||||||
val follow = Follow(createdBy = citizen, target = ArticleRef(articleId.toUUID()))
|
val follow = Follow(createdBy = citizen, target = ArticleRef(articleId.toUUID()))
|
||||||
get<FollowArticleRepository>().follow(follow)
|
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 com.auth0.jwt.JWT
|
||||||
import fr.dcproject.JwtConfig
|
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.cucumber.java8.En
|
||||||
import io.ktor.http.HttpHeaders
|
import io.ktor.http.HttpHeaders
|
||||||
import org.joda.time.DateTime
|
|
||||||
import org.koin.test.KoinTest
|
import org.koin.test.KoinTest
|
||||||
import org.koin.test.get
|
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
|
import fr.dcproject.repository.Citizen as CitizenRepository
|
||||||
|
|
||||||
class KtorServerAuthSteps : En, KoinTest {
|
class KtorServerAuthSteps : En, KoinTest {
|
||||||
private val requester: Requester by inject()
|
|
||||||
init {
|
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 ->
|
Given("I am authenticated as {word} {word}") { firstName: String, lastName: String ->
|
||||||
val username = "$firstName-$lastName".toLowerCase()
|
val username = "$firstName-$lastName".toLowerCase()
|
||||||
val citizen = get<CitizenRepository>().findByUsername(username) ?: error("Cititzen not exist with username $username")
|
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")
|
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
|
package feature
|
||||||
|
|
||||||
import fr.dcproject.entity.OpinionArticle
|
import fr.dcproject.entity.OpinionArticle
|
||||||
|
import fr.dcproject.entity.OpinionChoice
|
||||||
import fr.dcproject.utils.toUUID
|
import fr.dcproject.utils.toUUID
|
||||||
import io.cucumber.datatable.DataTable
|
import io.cucumber.datatable.DataTable
|
||||||
import io.cucumber.java8.En
|
import io.cucumber.java8.En
|
||||||
import org.koin.test.KoinTest
|
import org.koin.test.KoinTest
|
||||||
import org.koin.test.get
|
import org.koin.test.get
|
||||||
|
import java.util.*
|
||||||
import fr.dcproject.repository.Article as ArticleRepository
|
import fr.dcproject.repository.Article as ArticleRepository
|
||||||
import fr.dcproject.repository.Citizen as CitizenRepository
|
import fr.dcproject.repository.Citizen as CitizenRepository
|
||||||
import fr.dcproject.repository.OpinionArticle as OpinionRepository
|
import fr.dcproject.repository.OpinionArticle as OpinionRepository
|
||||||
@@ -13,33 +15,60 @@ import fr.dcproject.repository.OpinionChoice as OpinionChoiceRepository
|
|||||||
|
|
||||||
class OpinionSteps : En, KoinTest {
|
class OpinionSteps : En, KoinTest {
|
||||||
init {
|
init {
|
||||||
Given("I have the opinion {string} on article {string} created by {string}:") { opinionChoice: String, article: String, citizen: String, extraInfo: DataTable ->
|
Given("I have an opinion choice {string}") { name: String ->
|
||||||
extraInfo.asMap<String, String>(String::class.java, String::class.java).let {
|
val opinionChoice = OpinionChoice(
|
||||||
val opinion = OpinionArticle(
|
name = name,
|
||||||
choice = get<OpinionChoiceRepository>().findOpinionsChoiceByName(opinionChoice)
|
target = listOf()
|
||||||
?: error("Opinion Choice not exist"),
|
)
|
||||||
target = get<ArticleRepository>().findById(article.toUUID()) ?: error("Article not exist"),
|
get<OpinionRepository>().upsertOpinionChoice(opinionChoice)
|
||||||
createdBy = get<CitizenRepository>().findById(citizen.toUUID()) ?: error("Citizen not exist")
|
}
|
||||||
)
|
|
||||||
get<OpinionRepository>().opinion(opinion)
|
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 ->
|
Given("I have an opinion") { extraInfo: DataTable ->
|
||||||
extraInfo.asMap<String, String>(String::class.java, String::class.java)?.let { params ->
|
createOpinionOnArticle(extraInfo)
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 io.mockk.mockkStatic
|
||||||
import org.amshove.kluent.`should be`
|
import org.amshove.kluent.`should be`
|
||||||
import org.joda.time.DateTime
|
import org.joda.time.DateTime
|
||||||
|
import org.junit.jupiter.api.Tag
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import org.junit.jupiter.api.TestInstance
|
import org.junit.jupiter.api.TestInstance
|
||||||
|
|
||||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||||
|
@Tag("voter")
|
||||||
internal class ArticleVoterTest {
|
internal class ArticleVoterTest {
|
||||||
val tesla = CitizenBasic(
|
val tesla = CitizenBasic(
|
||||||
user = User(
|
user = User(
|
||||||
@@ -48,15 +50,13 @@ internal class ArticleVoterTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@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 article = getArticle(tesla)
|
||||||
val article2 = getArticle(tesla)
|
|
||||||
|
|
||||||
mockk<ApplicationCall> {
|
mockk<ApplicationCall> {
|
||||||
every { user } returns einstein.user
|
every { user } returns einstein.user
|
||||||
}.let {
|
}.let {
|
||||||
supports(ArticleVoter.Action.VIEW, it, article) `should be` true
|
can(ArticleVoter.Action.VIEW, it, article) `should be` true
|
||||||
vote(ArticleVoter.Action.VIEW, it, article) `should be` Vote.GRANTED
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,14 +73,13 @@ internal class ArticleVoterTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@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 }
|
val article = getArticle(tesla).apply { draft = true }
|
||||||
|
|
||||||
mockk<ApplicationCall> {
|
mockk<ApplicationCall> {
|
||||||
every { user } returns einstein.user
|
every { user } returns einstein.user
|
||||||
}.let {
|
}.let {
|
||||||
supports(ArticleVoter.Action.VIEW, it, article) `should be` true
|
can(ArticleVoter.Action.VIEW, it, article) `should be` false
|
||||||
vote(ArticleVoter.Action.VIEW, it, article) `should be` Vote.DENIED
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,62 +96,79 @@ internal class ArticleVoterTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@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() }
|
val article = getArticle(tesla).apply { deletedAt = DateTime.now() }
|
||||||
|
|
||||||
mockk<ApplicationCall> {
|
mockk<ApplicationCall> {
|
||||||
every { user } returns tesla.user
|
every { user } returns tesla.user
|
||||||
}.let {
|
}.let {
|
||||||
supports(ArticleVoter.Action.VIEW, it, article) `should be` true
|
can(ArticleVoter.Action.VIEW, it, article) `should be` false
|
||||||
vote(ArticleVoter.Action.VIEW, it, article) `should be` Vote.DENIED
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `can delete article if owner`() = ArticleVoter().run {
|
fun `can delete article if owner`() = listOf(ArticleVoter()).run {
|
||||||
val article = getArticle(tesla)
|
val article = getArticle(tesla)
|
||||||
|
|
||||||
mockk<ApplicationCall> {
|
mockk<ApplicationCall> {
|
||||||
every { user } returns tesla.user
|
every { user } returns tesla.user
|
||||||
}.let {
|
}.let {
|
||||||
supports(ArticleVoter.Action.DELETE, it, article) `should be` true
|
can(ArticleVoter.Action.DELETE, it, article) `should be` true
|
||||||
vote(ArticleVoter.Action.DELETE, it, article) `should be` Vote.GRANTED
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@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() }
|
val article = getArticle(tesla).apply { deletedAt = DateTime.now() }
|
||||||
|
|
||||||
mockk<ApplicationCall> {
|
mockk<ApplicationCall> {
|
||||||
every { user } returns einstein.user
|
every { user } returns einstein.user
|
||||||
}.let {
|
}.let {
|
||||||
supports(ArticleVoter.Action.DELETE, it, article) `should be` true
|
can(ArticleVoter.Action.DELETE, it, article) `should be` false
|
||||||
vote(ArticleVoter.Action.DELETE, it, article) `should be` Vote.DENIED
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `can create article if logged`() = ArticleVoter().run {
|
fun `can create article if logged`() = listOf(ArticleVoter()).run {
|
||||||
val article = getArticle(tesla)
|
val article = getArticle(tesla)
|
||||||
|
|
||||||
mockk<ApplicationCall> {
|
mockk<ApplicationCall> {
|
||||||
every { user } returns tesla.user
|
every { user } returns tesla.user
|
||||||
}.let {
|
}.let {
|
||||||
supports(ArticleVoter.Action.CREATE, it, article) `should be` true
|
can(ArticleVoter.Action.CREATE, it, article) `should be` true
|
||||||
vote(ArticleVoter.Action.CREATE, it, article) `should be` Vote.GRANTED
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@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)
|
val article = getArticle(tesla)
|
||||||
|
|
||||||
mockk<ApplicationCall> {
|
mockk<ApplicationCall> {
|
||||||
every { user } returns null
|
every { user } returns null
|
||||||
}.let {
|
}.let {
|
||||||
supports(ArticleVoter.Action.CREATE, it, article) `should be` true
|
can(ArticleVoter.Action.CREATE, it, article) `should be` false
|
||||||
vote(ArticleVoter.Action.CREATE, it, article) `should be` Vote.DENIED
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@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
|
Feature: articles routes
|
||||||
|
|
||||||
Scenario: The route for get articles must response a 200
|
Scenario: The route for get articles must response a 200
|
||||||
|
Given I have 3 article
|
||||||
When I send a GET request to "/articles"
|
When I send a GET request to "/articles"
|
||||||
Then the response status code should be 200
|
Then the response status code should be 200
|
||||||
|
|
||||||
Scenario: Can get versions of article by the id
|
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
|
Then the response status code should be 200
|
||||||
|
|
||||||
Scenario: The route for get one article must response a 200 and return article
|
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
|
Then the response status code should be 200
|
||||||
And the response should contain object:
|
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
|
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:
|
When I send a POST request to "/articles" with body:
|
||||||
"""
|
"""
|
||||||
{
|
{
|
||||||
@@ -27,10 +33,7 @@ Feature: articles routes
|
|||||||
"description": "description2",
|
"description": "description2",
|
||||||
"tags": [
|
"tags": [
|
||||||
"green"
|
"green"
|
||||||
],
|
]
|
||||||
"created_by": {
|
|
||||||
"id": "64b7b379-2298-43ec-b428-ba134930cabd"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
Then the response status code should be 200
|
Then the response status code should be 200
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
@auth
|
||||||
Feature: Auth routes
|
Feature: Auth routes
|
||||||
|
|
||||||
Scenario: The route for create citizen must response a 200 and return object
|
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
|
Then the response status code should be 400
|
||||||
|
|
||||||
Scenario: The route for create citizen must response a 200 and return object
|
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:
|
When I send a POST request to "/login" with body:
|
||||||
"""
|
"""
|
||||||
{
|
{
|
||||||
"name": "username-1",
|
"name": "niels-bohr",
|
||||||
"password": "azerty"
|
"password": "azerty"
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -1,31 +1,35 @@
|
|||||||
|
@citizen
|
||||||
Feature: citizens routes
|
Feature: citizens routes
|
||||||
|
|
||||||
Scenario: The route for get citizens must response a 200
|
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"
|
When I send a GET request to "/citizens"
|
||||||
Then the response status code should be 200
|
Then the response status code should be 200
|
||||||
|
|
||||||
Scenario: The route for get one citizen must response a 200 and return citizen
|
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"
|
Given I have citizen Linus Pauling with ID "47a05c0f-7329-46c3-a7d0-325db37e9114"
|
||||||
When I send a GET request to "/citizens/6434f4f9-f570-f22a-c134-8668350651ff"
|
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
|
Then the response status code should be 200
|
||||||
And the response should contain object:
|
And the response should contain object:
|
||||||
| id | 6434f4f9-f570-f22a-c134-8668350651ff |
|
| id | 47a05c0f-7329-46c3-a7d0-325db37e9114 |
|
||||||
|
|
||||||
Scenario: Can get connected citizen
|
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"
|
When I send a GET request to "/citizens/current"
|
||||||
Then the response status code should be 200
|
Then the response status code should be 200
|
||||||
And the response should contain object:
|
And the response should contain object:
|
||||||
| id | 64b7b379-2298-43ec-b428-ba134930cabd |
|
| id | 47356809-c8ef-4649-8b99-1c5cb9886d38 |
|
||||||
|
|
||||||
@online
|
@online
|
||||||
Scenario: Can be connect with SSO
|
Scenario: Can be connect with SSO
|
||||||
Given I have citizen:
|
Given I have citizen
|
||||||
| id | c606110c-ff0e-4d09-a79e-74632d7bf7bd |
|
| id | c606110c-ff0e-4d09-a79e-74632d7bf7bd |
|
||||||
| firstName | John |
|
|
||||||
| lastName | Doe |
|
|
||||||
| email | fabrice.lecomte.be@gmail.com |
|
| email | fabrice.lecomte.be@gmail.com |
|
||||||
|
| firstName | Leonhard |
|
||||||
|
| lastName | Euler |
|
||||||
When I send a POST request to "/sso" with body:
|
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
|
Then the response status code should be 204
|
||||||
|
|
||||||
Scenario: Can be change my password
|
Scenario: Can be change my password
|
||||||
Given I am authenticated as Joe Patate with id "c211dca6-aa21-45c2-95ba-c7f2179ee37e"
|
Given I have citizen Georges Charpak with ID "0c966522-4071-43e5-a3ca-cfff2557f2cf"
|
||||||
When I send a PUT request to "/citizens/c211dca6-aa21-45c2-95ba-c7f2179ee37e/password/change" with body:
|
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",
|
"old_password": "azerty",
|
||||||
@@ -47,8 +52,10 @@ Feature: citizens routes
|
|||||||
Then the response status code should be 201
|
Then the response status code should be 201
|
||||||
|
|
||||||
Scenario: If a send bad request when a change password, that return a 400 Bad request
|
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",
|
"plup": "azerty",
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
|
@comment
|
||||||
Feature: comment
|
Feature: comment
|
||||||
|
|
||||||
Scenario: Can comment childrens
|
Scenario: Can comment childrens
|
||||||
Given I am authenticated as John Doe with id "64b7b379-2298-43ec-b428-ba134930cabd"
|
Given I have citizen John Dalton
|
||||||
And I have article with id "9226c1a3-8091-c3fa-7d0d-c2e98c9bee7b"
|
And I am authenticated as John Dalton
|
||||||
When I send a GET request to "/comments/9226c1a3-8091-c3fa-7d0d-c2e98c9bee7b/children"
|
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
|
Then the response status code should be 200
|
||||||
@@ -1,9 +1,12 @@
|
|||||||
|
@comment
|
||||||
Feature: comment Article
|
Feature: comment Article
|
||||||
|
|
||||||
Scenario: Can comment an article
|
Scenario: Can comment an article
|
||||||
Given I am authenticated as John Doe with id "64b7b379-2298-43ec-b428-ba134930cabd"
|
Given I have citizen Michael Faraday
|
||||||
And I have article with id "9226c1a3-8091-c3fa-7d0d-c2e98c9bee7b"
|
And I am authenticated as Michael Faraday
|
||||||
When I send a POST request to "/articles/9226c1a3-8091-c3fa-7d0d-c2e98c9bee7b/comments" with body:
|
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"
|
"content": "Hello mister"
|
||||||
@@ -11,32 +14,52 @@ Feature: comment Article
|
|||||||
"""
|
"""
|
||||||
Then the response status code should be 201
|
Then the response status code should be 201
|
||||||
|
|
||||||
|
# TODO add more comment on article
|
||||||
Scenario: Can get all comment on article
|
Scenario: Can get all comment on article
|
||||||
Given I am authenticated as John Doe with id "64b7b379-2298-43ec-b428-ba134930cabd"
|
Given I have citizen Enrico Fermi
|
||||||
And I have article with id "9226c1a3-8091-c3fa-7d0d-c2e98c9bee7b"
|
And I am authenticated as Enrico Fermi
|
||||||
When I send a GET request to "/articles/9226c1a3-8091-c3fa-7d0d-c2e98c9bee7b/comments"
|
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
|
Then the response status code should be 200
|
||||||
|
|
||||||
|
# TODO add votes
|
||||||
Scenario: Can get all comment on article sorted by 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"
|
Given I have citizen Pierre Curie
|
||||||
And I have article with id "9226c1a3-8091-c3fa-7d0d-c2e98c9bee7b"
|
And I am authenticated as Pierre Curie
|
||||||
When I send a GET request to "/articles/9226c1a3-8091-c3fa-7d0d-c2e98c9bee7b/comments?sort=votes"
|
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
|
Then the response status code should be 200
|
||||||
And the response should contain object:
|
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
|
Scenario: Can get comments on articles of the current citizen
|
||||||
Given I have citizen John Doe with id "64b7b379-2298-43ec-b428-ba134930cabd"
|
Given I have citizen Erwin Schrodinger with ID "292a20cc-4a60-489e-9866-a95d38ffaf47"
|
||||||
And I have article with id "9226c1a3-8091-c3fa-7d0d-c2e98c9bee7b"
|
And I have article
|
||||||
When I send a GET request to "/citizens/64b7b379-2298-43ec-b428-ba134930cabd/comments/articles"
|
| 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
|
Then the response status code should be 200
|
||||||
And the response should contain object:
|
And the response should contain object:
|
||||||
| current_page | 1 |
|
| current_page | 1 |
|
||||||
| limit | 50 |
|
| limit | 50 |
|
||||||
|
And the Response should contain:
|
||||||
|
"""
|
||||||
|
292a20cc-4a60-489e-9866-a95d38ffaf47
|
||||||
|
"""
|
||||||
|
|
||||||
Scenario: Can edit a comment
|
Scenario: Can edit a comment
|
||||||
Given I am authenticated as username 3 with id "92877af7-0a45-fd6a-2ed7-fe81e1236b78"
|
Given I have citizen Hubert Reeves
|
||||||
When I send a PUT request to "/comments/2f01c257-cf20-3466-fb10-a3b8eff12a97" with body:
|
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
|
Hello boy
|
||||||
"""
|
"""
|
||||||
@@ -45,7 +68,13 @@ Feature: comment Article
|
|||||||
| content | Hello boy |
|
| content | Hello boy |
|
||||||
|
|
||||||
Scenario: Can get comment by its ID
|
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
|
Then the response status code should be 200
|
||||||
And the JSON should contain:
|
And the JSON should contain:
|
||||||
| content | Hello boy |
|
| content | Hello boy |
|
||||||
|
|||||||
@@ -1,35 +1,31 @@
|
|||||||
|
@comment
|
||||||
Feature: comment Constitution
|
Feature: comment Constitution
|
||||||
|
|
||||||
Scenario: Can comment an constitution
|
Scenario: Can comment an constitution
|
||||||
Given I am authenticated as John Toe with id "a6eb1f5a-8c02-42f4-8e8e-a722f26841ef"
|
Given I have citizen Nicolas Copernic
|
||||||
And I have constitution with id "d7e20f0b-3fdd-4638-817a-bbd87054eb82" created by "john-toe"
|
And I am authenticated as Nicolas Copernic
|
||||||
When I send a POST request to "/constitutions/d7e20f0b-3fdd-4638-817a-bbd87054eb82/comments" with body:
|
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
|
Then the response status code should be 201
|
||||||
|
|
||||||
Scenario: Can get comments on constitution of the current citizen
|
Scenario: Can get comments on constitutions of the current citizen
|
||||||
Given I have citizen John Doe with id "64b7b379-2298-43ec-b428-ba134930cabd"
|
Given I have citizen Charles Darwin with ID "46e0bda9-ca6a-4c65-a58b-7e7267a0bbc5"
|
||||||
And I have constitution with id "9226c1a3-8091-c3fa-7d0d-c2e98c9bee7b"
|
And I have constitution
|
||||||
When I send a GET request to "/citizens/64b7b379-2298-43ec-b428-ba134930cabd/comments/constitutions"
|
| 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
|
Then the response status code should be 200
|
||||||
And the response should contain object:
|
And the response should contain object:
|
||||||
| current_page | 1 |
|
| current_page | 1 |
|
||||||
| limit | 50 |
|
| limit | 50 |
|
||||||
|
And the Response should contain:
|
||||||
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:
|
|
||||||
"""
|
"""
|
||||||
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
|
Scenario: The route for get constitutions must response a 200
|
||||||
|
Given I have 3 constitution
|
||||||
When I send a GET request to "/constitutions"
|
When I send a GET request to "/constitutions"
|
||||||
Then the response status code should be 200
|
Then the response status code should be 200
|
||||||
|
|
||||||
Scenario: The route for get one constitution must response a 200 and return constitution
|
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
|
Then the response status code should be 200
|
||||||
And the response should contain object:
|
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
|
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:
|
When I send a POST request to "/constitutions" with body:
|
||||||
"""
|
"""
|
||||||
{
|
{
|
||||||
@@ -20,19 +24,10 @@ Feature: constitution routes
|
|||||||
"annonymous":true,
|
"annonymous":true,
|
||||||
"titles":[
|
"titles":[
|
||||||
{
|
{
|
||||||
"id":"8156b66f-a9c8-4fd9-8375-a8a1f42ccfd2",
|
|
||||||
"name":"plop",
|
"name":"plop",
|
||||||
"rank":0,
|
"rank":0
|
||||||
"created_by":{
|
|
||||||
"id":"64b7b379-2298-43ec-b428-ba134930cabd"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
],
|
]
|
||||||
"created_by":{
|
|
||||||
"id":"64b7b379-2298-43ec-b428-ba134930cabd"
|
|
||||||
},
|
|
||||||
"created_at":null,
|
|
||||||
"version_number":null
|
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
Then the response status code should be 200
|
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
|
@opinion
|
||||||
Feature: 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
|
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"
|
When I send a GET request to "/opinions"
|
||||||
Then the response status code should be 200
|
Then the response status code should be 200
|
||||||
And the JSON should contain:
|
And the JSON should contain:
|
||||||
| [0]name | Opinion1 |
|
| [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
|
Scenario: Can create opinion on article
|
||||||
Given I have citizen:
|
Given I have citizen Isaac Newton with ID "2f414045-95d9-42ca-a3a9-8cdde52ad253"
|
||||||
| id | 2f414045-95d9-42ca-a3a9-8cdde52ad253 |
|
|
||||||
| firstName | Isaac |
|
|
||||||
| lastName | Newton |
|
|
||||||
And I am authenticated as Isaac Newton
|
And I am authenticated as Isaac Newton
|
||||||
And I have article
|
And I have article
|
||||||
| id | 9226c1a3-8091-c3fa-7d0d-c2e98c9bee7 |
|
| id | 9226c1a3-8091-c3fa-7d0d-c2e98c9bee7b |
|
||||||
| createdBy | Isaac Newton |
|
|
||||||
And I have an opinion
|
|
||||||
| opinion | Opinion1 |
|
|
||||||
| article | 9226c1a3-8091-c3fa-7d0d-c2e98c9bee7b |
|
|
||||||
| createdBy | Isaac Newton |
|
| 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:
|
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
|
Then the response status code should be 201
|
||||||
|
|
||||||
Scenario: Can I get all opinions of citizen filtered by target ids
|
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
|
Then the response status code should be 200
|
||||||
And the JSON should contain:
|
And the JSON should contain:
|
||||||
| [0].name | Opinion2 |
|
| [0].name | Opinion5 |
|
||||||
|
|
||||||
Scenario: Can recieve opinion aggregation with article
|
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
|
Then the response status code should be 200
|
||||||
And the JSON should contain:
|
And the JSON should contain:
|
||||||
| opinions.Opinion2 | 1 |
|
| opinions.Opinion6 | 1 |
|
||||||
|
| opinions.Opinion7 | 2 |
|
||||||
|
|
||||||
Scenario: Can get all opinion of one citizen
|
Scenario: Can get all opinion of one citizen
|
||||||
Given I have citizen:
|
Given I have citizen Albert Einstein with ID "c1542096-3431-432d-8e35-9dc071d4c818"
|
||||||
| id | c1542096-3431-432d-8e35-9dc071d4c818 |
|
|
||||||
| firstName | Albert |
|
|
||||||
| lastName | Einstein |
|
|
||||||
And I am authenticated as Albert Einstein
|
And I am authenticated as Albert Einstein
|
||||||
And I have an opinion
|
And I have an opinion choice "Opinion9"
|
||||||
| opinion | Opinion1 |
|
And I have article with ID "8651b530-ac1b-4214-a784-706781371074"
|
||||||
| article | 9226c1a3-8091-c3fa-7d0d-c2e98c9bee7b |
|
And I have an opinion "Opinion9" on article "8651b530-ac1b-4214-a784-706781371074" created by Albert Einstein
|
||||||
| createdBy | Albert Einstein |
|
|
||||||
When I send a GET request to "/citizens/c1542096-3431-432d-8e35-9dc071d4c818/opinions/articles"
|
When I send a GET request to "/citizens/c1542096-3431-432d-8e35-9dc071d4c818/opinions/articles"
|
||||||
Then the response status code should be 200
|
Then the response status code should be 200
|
||||||
And the JSON element result should have 1 items
|
And the JSON element result should have 1 items
|
||||||
And the JSON should contain:
|
And the JSON should contain:
|
||||||
| result[0].name | Opinion1 |
|
| result[0].name | Opinion9 |
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
|
@vote
|
||||||
Feature: vote Article
|
Feature: vote Article
|
||||||
|
|
||||||
Scenario: Can Vote article
|
Scenario: Can Vote article
|
||||||
Given I am authenticated as John Doe with id "64b7b379-2298-43ec-b428-ba134930cabd"
|
Given I have citizen Thalès Milet
|
||||||
When I send a PUT request to "/articles/9226c1a3-8091-c3fa-7d0d-c2e98c9bee7b/vote" with body:
|
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
|
"note": 1
|
||||||
@@ -11,8 +14,10 @@ Feature: vote Article
|
|||||||
Then the response status code should be 201
|
Then the response status code should be 201
|
||||||
|
|
||||||
Scenario: Can Vote constitution
|
Scenario: Can Vote constitution
|
||||||
Given I am authenticated as John Doe with id "64b7b379-2298-43ec-b428-ba134930cabd"
|
Given I have citizen Gregor Mendel
|
||||||
When I send a PUT request to "/constitutions/64b1f265-bfb3-332b-eef9-d00f63a3beaa/vote" with body:
|
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
|
"note": -1
|
||||||
@@ -21,8 +26,11 @@ Feature: vote Article
|
|||||||
Then the response status code should be 201
|
Then the response status code should be 201
|
||||||
|
|
||||||
Scenario: Can get votes of current citizen
|
Scenario: Can get votes of current citizen
|
||||||
Given I am authenticated as John Doe with id "64b7b379-2298-43ec-b428-ba134930cabd"
|
Given I have citizen Carl Gauss with ID "c044823d-e778-4256-9016-b1334bf933d3"
|
||||||
When I send a GET request to "/citizens/64b7b379-2298-43ec-b428-ba134930cabd/votes/articles"
|
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
|
Then the response status code should be 200
|
||||||
And the response should contain object:
|
And the response should contain object:
|
||||||
| current_page | 1 |
|
| current_page | 1 |
|
||||||
@@ -31,16 +39,25 @@ Feature: vote Article
|
|||||||
| result[0].note | 1 |
|
| result[0].note | 1 |
|
||||||
|
|
||||||
Scenario: Can get votes of current citizen by target ids
|
Scenario: Can get votes of current citizen by target ids
|
||||||
Given I am authenticated as John Doe with id "64b7b379-2298-43ec-b428-ba134930cabd"
|
Given I have citizen Rosalind Franklin with ID "ab3269f0-877b-46b2-ae1a-e7e7d1c12132"
|
||||||
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"
|
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
|
Then the response status code should be 200
|
||||||
And the response should contain object:
|
And the response should contain object:
|
||||||
| [0].note | 1 |
|
| [0].note | -1 |
|
||||||
|
| [1].note | 1 |
|
||||||
|
|
||||||
Scenario: Can vote a comment
|
Scenario: Can vote a comment
|
||||||
Given I am authenticated as John Doe with id "64b7b379-2298-43ec-b428-ba134930cabd"
|
Given I have citizen Antoine Lavoisier
|
||||||
And I have comment "ea5c9e87-c99e-4646-a381-2910219e077f" on article "cc9c624e-a27e-42de-af78-ae821c657a68"
|
And I am authenticated as Antoine Lavoisier
|
||||||
When I send a PUT request to "/comments/ea5c9e87-c99e-4646-a381-2910219e077f/vote" with body:
|
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
|
"note": -1
|
||||||
|
|||||||
@@ -45,8 +45,8 @@ Feature: Workgroup
|
|||||||
|
|
||||||
Scenario: Can add member to workgroup
|
Scenario: Can add member to workgroup
|
||||||
Given I have citizen Blaise Pascal
|
Given I have citizen Blaise Pascal
|
||||||
And I have citizen Roger Penrose with id "6d883fe7-5fc0-4a50-8858-72230673eba4"
|
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 Alessandro Volta with ID "b5bac515-45d4-4aeb-9b6d-2627a0bbc419"
|
||||||
And I am authenticated as Blaise Pascal
|
And I am authenticated as Blaise Pascal
|
||||||
And I have workgroup:
|
And I have workgroup:
|
||||||
| id | b0ea1922-3bc6-44e2-aa7c-40158998cfbb |
|
| id | b0ea1922-3bc6-44e2-aa7c-40158998cfbb |
|
||||||
@@ -63,8 +63,8 @@ Feature: Workgroup
|
|||||||
|
|
||||||
Scenario: Can remove member to workgroup
|
Scenario: Can remove member to workgroup
|
||||||
Given I have citizen Heinrich Hertz
|
Given I have citizen Heinrich Hertz
|
||||||
And I have citizen William Thomson with id "87909ba3-2069-431c-9924-219fd8411cf2"
|
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 Paul Dirac with ID "1baf48bb-02bc-4d8f-ac86-33335354f5e7"
|
||||||
And I am authenticated as Heinrich Hertz
|
And I am authenticated as Heinrich Hertz
|
||||||
And I have workgroup:
|
And I have workgroup:
|
||||||
| id | b6c975df-dd44-4e99-adc1-f605746b0e11 |
|
| id | b6c975df-dd44-4e99-adc1-f605746b0e11 |
|
||||||
@@ -85,15 +85,15 @@ Feature: Workgroup
|
|||||||
And the JSON should have 1 items
|
And the JSON should have 1 items
|
||||||
|
|
||||||
Scenario: Can update members on workgroup
|
Scenario: Can update members on workgroup
|
||||||
Given I have citizen 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 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 Joseph Fourier with ID "d9671eca-abaf-4b67-9230-3ece700c1ddb"
|
||||||
And I have citizen Georg Ohm with id "b49e20c1-8393-45d6-a6a0-3fa5c71cbdc1"
|
And I have citizen Georg Ohm with ID "b49e20c1-8393-45d6-a6a0-3fa5c71cbdc1"
|
||||||
And I am authenticated as John Dalton
|
And I am authenticated as Leon Foucault
|
||||||
And I have workgroup:
|
And I have workgroup:
|
||||||
| id | 784fe6bc-7635-4ae2-b080-3a4743b998bf |
|
| id | 784fe6bc-7635-4ae2-b080-3a4743b998bf |
|
||||||
| name | Les Tacos |
|
| name | Les Tacos |
|
||||||
| owner | John Dalton |
|
| owner | Leon Foucault |
|
||||||
And I have members in workgroup "784fe6bc-7635-4ae2-b080-3a4743b998bf":
|
And I have members in workgroup "784fe6bc-7635-4ae2-b080-3a4743b998bf":
|
||||||
| be3b0926-8628-4426-804a-75188a6eb315 |
|
| be3b0926-8628-4426-804a-75188a6eb315 |
|
||||||
| d9671eca-abaf-4b67-9230-3ece700c1ddb |
|
| d9671eca-abaf-4b67-9230-3ece700c1ddb |
|
||||||
|
|||||||
@@ -58,15 +58,10 @@ begin
|
|||||||
-- upsert article
|
-- upsert article
|
||||||
select upsert_article(created_article) into created_article;
|
select upsert_article(created_article) into created_article;
|
||||||
|
|
||||||
|
select (h->>'id')::uuid into opinion_choice1_id from upsert_opinion_choice('{"name": "Opinion1", "target":["article"]}') h;
|
||||||
insert into opinion_choice(id, name, target)
|
assert opinion_choice1_id is not null, 'Opinion choice must be return json with id';
|
||||||
values (opinion_choice1_id, 'Opinion1', '{article}');
|
select (h->>'id')::uuid into opinion_choice2_id from upsert_opinion_choice('{"name": "Opinion2"}') h;
|
||||||
|
perform upsert_opinion_choice('{"name": "Opinion3", "target":["article"]}') h;
|
||||||
insert into opinion_choice(id, name)
|
|
||||||
values (opinion_choice2_id, 'Opinion2');
|
|
||||||
|
|
||||||
insert into opinion_choice(name, target)
|
|
||||||
values ('Opinion3', '{article}');
|
|
||||||
|
|
||||||
perform upsert_opinion(
|
perform upsert_opinion(
|
||||||
resource => json_build_object(
|
resource => json_build_object(
|
||||||
|
|||||||
Reference in New Issue
Block a user