Continue to implement opinion
improve target reference Improve Tests for Opinion fix SQL:upsert_opinion
This commit is contained in:
@@ -7,6 +7,7 @@ import fr.dcproject.module
|
||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||
import io.ktor.server.testing.withTestApplication
|
||||
import io.ktor.util.KtorExperimentalAPI
|
||||
import org.junit.jupiter.api.Tag
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
import org.koin.test.AutoCloseKoinTest
|
||||
@@ -18,6 +19,7 @@ import org.koin.test.get
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
class MailerTest : KoinTest, AutoCloseKoinTest() {
|
||||
@Test
|
||||
@Tag("online")
|
||||
fun `can be send an email`() {
|
||||
withTestApplication({ module(Env.TEST) }) {
|
||||
get<Mailer>().sendEmail {
|
||||
|
||||
@@ -6,8 +6,8 @@ import fr.dcproject.utils.LoggerDelegate
|
||||
import fr.postgresjson.connexion.Connection
|
||||
import fr.postgresjson.connexion.Requester
|
||||
import fr.postgresjson.migration.Migrations
|
||||
import io.cucumber.core.api.Scenario
|
||||
import io.cucumber.java8.En
|
||||
import io.cucumber.java8.Scenario
|
||||
import io.cucumber.junit.Cucumber
|
||||
import io.cucumber.junit.CucumberOptions
|
||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||
|
||||
@@ -2,6 +2,8 @@ package feature
|
||||
|
||||
import fr.dcproject.entity.*
|
||||
import fr.dcproject.repository.CommentArticle
|
||||
import fr.dcproject.utils.toUUID
|
||||
import io.cucumber.datatable.DataTable
|
||||
import io.cucumber.java8.En
|
||||
import org.joda.time.DateTime
|
||||
import org.koin.test.KoinTest
|
||||
@@ -16,6 +18,9 @@ import fr.dcproject.repository.Citizen as CitizenRepository
|
||||
|
||||
class ArticleSteps : En, KoinTest {
|
||||
init {
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
Given("I have article with id {string}") { id: String ->
|
||||
var citizen = Citizen(
|
||||
name = CitizenI.Name("John", "Doe"),
|
||||
@@ -40,6 +45,23 @@ class ArticleSteps : En, KoinTest {
|
||||
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 ->
|
||||
val citizen = get<CitizenRepository>().findByUsername(username)!!
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import fr.dcproject.JwtConfig
|
||||
import fr.dcproject.entity.Citizen
|
||||
import fr.dcproject.entity.CitizenI
|
||||
import fr.dcproject.entity.User
|
||||
import fr.dcproject.utils.toUUID
|
||||
import fr.postgresjson.connexion.Requester
|
||||
import io.cucumber.datatable.DataTable
|
||||
import io.cucumber.java8.En
|
||||
@@ -70,6 +71,38 @@ class KtorServerAuthSteps : En, KoinTest {
|
||||
}
|
||||
}
|
||||
|
||||
Given("I have citizen {word} {word}") { firstName: String, lastName: String, extraInfo: DataTable? ->
|
||||
val id: UUID = extraInfo?.asMap<String, String>(String::class.java, String::class.java)?.get("id")?.toUUID() ?: UUID.randomUUID()
|
||||
|
||||
val user = User(
|
||||
id = id,
|
||||
username = "$firstName-$lastName".toLowerCase(),
|
||||
plainPassword = "azerty"
|
||||
)
|
||||
val citizen = Citizen(
|
||||
id = id,
|
||||
name = CitizenI.Name(firstName, lastName),
|
||||
email = ("$firstName-$lastName".toLowerCase()) + "@dc-project.fr",
|
||||
birthday = DateTime.now(),
|
||||
user = user
|
||||
)
|
||||
|
||||
get<CitizenRepository>().insertWithUser(citizen)
|
||||
}
|
||||
|
||||
Given("I am authenticated as {word} {word}") { firstName: String, lastName: String ->
|
||||
val username = "$firstName-$lastName".toLowerCase()
|
||||
val citizen = get<CitizenRepository>().findByUsername(username) ?: error("Cititzen not exist with username $username")
|
||||
val jwtAsString: String = JWT.create()
|
||||
.withIssuer("dc-project.fr")
|
||||
.withClaim("id", citizen.id.toString())
|
||||
.sign(JwtConfig.algorithm)
|
||||
|
||||
KtorServerContext.defaultServer.addPreRequestSetup {
|
||||
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(),
|
||||
|
||||
@@ -41,20 +41,20 @@ class KtorServerRestSteps : En {
|
||||
}
|
||||
}
|
||||
|
||||
private fun findJsonElement(node: String): JsonElement {
|
||||
private fun findJsonElement(path: String): JsonElement {
|
||||
var jsonElement: JsonElement = responseJsonElement
|
||||
val elements = node.split(".")
|
||||
|
||||
elements.forEach {
|
||||
val asArrayIndex = """\d+""".toRegex().find(it)
|
||||
|
||||
jsonElement = if (asArrayIndex != null) {
|
||||
val index = asArrayIndex.groups.first()!!
|
||||
jsonElement.jsonArray.get(index.value.toInt())
|
||||
} else {
|
||||
jsonElement.jsonObject.get(it) ?: throw AssertionError("\"$node\" element not found on json response")
|
||||
path
|
||||
.split("].", "]", "[", ".")
|
||||
.filter { it.trim().isNotBlank() }
|
||||
.map { it.trim() }
|
||||
.forEach {
|
||||
jsonElement = if (jsonElement is JsonArray) {
|
||||
jsonElement.jsonArray[it.toInt()]
|
||||
} else {
|
||||
jsonElement.jsonObject[it]
|
||||
} ?: throw AssertionError("\"$path\" element not found on json response")
|
||||
}
|
||||
}
|
||||
|
||||
return jsonElement
|
||||
}
|
||||
|
||||
40
src/test/kotlin/feature/OpinionSteps.kt
Normal file
40
src/test/kotlin/feature/OpinionSteps.kt
Normal file
@@ -0,0 +1,40 @@
|
||||
package feature
|
||||
|
||||
import fr.dcproject.entity.OpinionArticle
|
||||
import fr.dcproject.utils.toUUID
|
||||
import io.cucumber.datatable.DataTable
|
||||
import io.cucumber.java8.En
|
||||
import org.koin.test.KoinTest
|
||||
import org.koin.test.get
|
||||
import fr.dcproject.repository.Article as ArticleRepository
|
||||
import fr.dcproject.repository.Citizen as CitizenRepository
|
||||
import fr.dcproject.repository.OpinionArticle as OpinionRepository
|
||||
import fr.dcproject.repository.OpinionChoice as OpinionChoiceRepository
|
||||
|
||||
|
||||
class OpinionSteps : En, KoinTest {
|
||||
init {
|
||||
Given("I have the opinion {string} on article {string} created by {string}:") { opinionChoice: String, article: String, citizen: String, extraInfo: DataTable ->
|
||||
extraInfo.asMap<String, String>(String::class.java, String::class.java).let {
|
||||
val opinion = OpinionArticle(
|
||||
choice = get<OpinionChoiceRepository>().findOpinionsChoiceByName(opinionChoice) ?: error("Opinion Choice not exist"),
|
||||
target = get<ArticleRepository>().findById(article.toUUID()) ?: error("Article not exist"),
|
||||
createdBy = get<CitizenRepository>().findById(citizen.toUUID()) ?: error("Citizen not exist")
|
||||
)
|
||||
get<OpinionRepository>().opinion(opinion)
|
||||
}
|
||||
}
|
||||
|
||||
Given("I have an opinion") { extraInfo: DataTable ->
|
||||
extraInfo.asMap<String, String>(String::class.java, String::class.java)?.let { params ->
|
||||
val username = params["createdBy"]?.toLowerCase()?.replace(' ', '-') ?: error("You must provide the 'createdBy' parameter")
|
||||
val opinion = OpinionArticle(
|
||||
choice = params["opinion"]?.let { get<OpinionChoiceRepository>().findOpinionsChoiceByName(it) ?: error("Opinion Choice not exist")} ?: error("You must provide the 'opinion' parameter"),
|
||||
target = params["article"]?.let { get<ArticleRepository>().findById(it.toUUID()) ?: error("Article not exist")} ?: error("You must provide the 'article' parameter"),
|
||||
createdBy = get<CitizenRepository>().findByUsername(username) ?: error("Citizen not exist")
|
||||
)
|
||||
get<OpinionRepository>().opinion(opinion)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@ Feature: citizens routes
|
||||
And the response should contain object:
|
||||
| id | 64b7b379-2298-43ec-b428-ba134930cabd |
|
||||
|
||||
@online
|
||||
Scenario: Can be connect with SSO
|
||||
Given I have citizen:
|
||||
| id | c606110c-ff0e-4d09-a79e-74632d7bf7bd |
|
||||
|
||||
59
src/test/resources/feature/opinion.feature
Normal file
59
src/test/resources/feature/opinion.feature
Normal file
@@ -0,0 +1,59 @@
|
||||
@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
|
||||
When I send a GET request to "/opinions"
|
||||
Then the response status code should be 200
|
||||
And the JSON should contain:
|
||||
| [0]name | Opinion1 |
|
||||
|
||||
Scenario: Can create opinion on article
|
||||
Given I have citizen Isaac Newton
|
||||
| id | 2f414045-95d9-42ca-a3a9-8cdde52ad253 |
|
||||
And I am authenticated as Isaac Newton
|
||||
And I have article
|
||||
| id | 9226c1a3-8091-c3fa-7d0d-c2e98c9bee7 |
|
||||
| createdBy | Isaac Newton |
|
||||
And I have an opinion
|
||||
| opinion | Opinion1 |
|
||||
| article | 9226c1a3-8091-c3fa-7d0d-c2e98c9bee7b |
|
||||
| createdBy | Isaac Newton |
|
||||
When I send a PUT request to "/articles/9226c1a3-8091-c3fa-7d0d-c2e98c9bee7b/opinions" with body:
|
||||
"""
|
||||
{
|
||||
"opinion_choice": "6e978eb5-3c48-0def-b093-e01f43983adb"
|
||||
}
|
||||
"""
|
||||
Then the response status code should be 201
|
||||
|
||||
Scenario: Can I get all opinions of citizen filtered by target ids
|
||||
When I send a GET request to "/citizens/6434f4f9-f570-f22a-c134-8668350651ff/opinions?id=9226c1a3-8091-c3fa-7d0d-c2e98c9bee7b"
|
||||
Then the response status code should be 200
|
||||
And the JSON should contain:
|
||||
| [0].name | Opinion2 |
|
||||
|
||||
Scenario: Can recieve opinion aggregation with article
|
||||
When I send a GET request to "/articles/9226c1a3-8091-c3fa-7d0d-c2e98c9bee7b"
|
||||
Then the response status code should be 200
|
||||
And the JSON should contain:
|
||||
| opinions.Opinion2 | 1 |
|
||||
|
||||
Scenario: Can get all opinion of one citizen
|
||||
Given I have citizen Albert Einstein
|
||||
| id | c1542096-3431-432d-8e35-9dc071d4c818 |
|
||||
And I am authenticated as Albert Einstein
|
||||
And I have an opinion
|
||||
| opinion | Opinion1 |
|
||||
| article | 9226c1a3-8091-c3fa-7d0d-c2e98c9bee7b |
|
||||
| createdBy | Albert Einstein |
|
||||
When I send a GET request to "/citizens/c1542096-3431-432d-8e35-9dc071d4c818/opinions/articles"
|
||||
Then the response status code should be 200
|
||||
And the JSON element result should have 1 items
|
||||
And the JSON should contain:
|
||||
| result[0].name | Opinion1 |
|
||||
@@ -38,8 +38,9 @@ declare
|
||||
"draft":false
|
||||
}
|
||||
$json$;
|
||||
opinion1 uuid = uuid_generate_v4();
|
||||
opinion2 uuid = uuid_generate_v4();
|
||||
opinion_choice1_id uuid = uuid_generate_v4();
|
||||
opinion_choice2_id uuid = uuid_generate_v4();
|
||||
opinion2 json;
|
||||
begin
|
||||
-- insert user for context
|
||||
select insert_user(created_user) into created_user;
|
||||
@@ -59,32 +60,38 @@ begin
|
||||
|
||||
|
||||
insert into opinion_choice(id, name, target)
|
||||
values (opinion1, 'Opinion1', '{article}');
|
||||
values (opinion_choice1_id, 'Opinion1', '{article}');
|
||||
|
||||
insert into opinion_choice(id, name, target)
|
||||
values (opinion2, 'Opinion2', '{article}');
|
||||
insert into opinion_choice(id, name)
|
||||
values (opinion_choice2_id, 'Opinion2');
|
||||
|
||||
insert into opinion_choice(name, target)
|
||||
values ('Opinion3', '{article}');
|
||||
|
||||
perform opinion(
|
||||
reference => 'article'::regclass,
|
||||
_target_id => (created_article->>'id')::uuid,
|
||||
_created_by_id => _citizen_id,
|
||||
_opinion => opinion1
|
||||
);
|
||||
perform opinion(
|
||||
reference => 'article'::regclass,
|
||||
_target_id => (created_article->>'id')::uuid,
|
||||
_created_by_id => _citizen_id,
|
||||
_opinion => opinion2
|
||||
perform upsert_opinion(
|
||||
resource => json_build_object(
|
||||
'target', json_build_object('id', (created_article->'id'), 'reference', 'article'),
|
||||
'created_by', json_build_object('id', _citizen_id),
|
||||
'choice', json_build_object('id', opinion_choice1_id)
|
||||
)
|
||||
);
|
||||
select upsert_opinion(
|
||||
resource => json_build_object(
|
||||
'target', json_build_object('id', (created_article->'id'), 'reference', 'article'),
|
||||
'created_by', json_build_object('id', _citizen_id),
|
||||
'choice', json_build_object('id', opinion_choice2_id)
|
||||
)
|
||||
) into opinion2;
|
||||
assert (select count(*) = 2 from opinion_on_article), 'opinions must be inserted';
|
||||
assert (select choice_id = opinion1 from opinion_on_article limit 1), 'opinion must be inserted';
|
||||
assert (select choice_id = opinion_choice1_id from opinion_on_article limit 1), 'opinion must be inserted';
|
||||
|
||||
assert(select (a#>>'{opinions, Opinion1}')::int = 1
|
||||
from find_article_by_id((created_article->>'id')::uuid) a), 'the article must be have a opinion';
|
||||
|
||||
raise notice '%', opinion2;
|
||||
assert(select (opinion2#>>'{choice, id}')::uuid = opinion_choice2_id), 'opinion2 is not inserted';
|
||||
assert(select (opinion2#>>'{choice, name}') = 'Opinion2'), 'no name for opinion2';
|
||||
|
||||
assert(
|
||||
select (o#>>'{0, choice, name}') = 'Opinion1'
|
||||
from find_citizen_opinions_by_target_id(_citizen_id, (created_article->>'id')::uuid) o),
|
||||
@@ -100,7 +107,11 @@ begin
|
||||
), 'find_opinion_choices must be return all opinions';
|
||||
|
||||
assert(
|
||||
select (find_opinion_choice_by_id(opinion1)->>'name') = 'Opinion1'
|
||||
select find_opinion_choices('{}')#>>'{0, name}' = 'Opinion1'
|
||||
), 'find_opinion_choices must be return all opinions if no target is defined';
|
||||
|
||||
assert(
|
||||
select (find_opinion_choice_by_id(opinion_choice1_id)->>'name') = 'Opinion1'
|
||||
), 'find_opinion_choice_by_id must return the opinion_choice';
|
||||
|
||||
assert(
|
||||
|
||||
Reference in New Issue
Block a user