fixs and move files
This commit is contained in:
1 parent
63a50dcb92
commit
7c3028eca2
60 files changed
+171
-105
No files matched your search
@@ -47,9 +47,3 @@ dependencies {
|
||||
testImplementation("io.cucumber:cucumber-java8:4.3.1")
|
||||
testImplementation("io.cucumber:cucumber-junit:4.3.1")
|
||||
}
|
||||
|
||||
kotlin.sourceSets["main"].kotlin.srcDirs("src")
|
||||
kotlin.sourceSets["test"].kotlin.srcDirs("test")
|
||||
|
||||
sourceSets["main"].resources.srcDirs("resources")
|
||||
sourceSets["test"].resources.srcDirs("testresources")
|
||||
@@ -1,18 +0,0 @@
|
||||
create or replace procedure insert_user(inout resource json) language plpgsql as
|
||||
$$
|
||||
declare
|
||||
new_id uuid;
|
||||
begin
|
||||
insert into "user" (username, password, blocked_at)
|
||||
select
|
||||
username,
|
||||
crypt(resource->>'plain_password', gen_salt('bf', 8)),
|
||||
case when blocked_at is not null then now() else null end
|
||||
from json_populate_record(null::"user", resource)
|
||||
returning id into new_id;
|
||||
|
||||
select find_user_by_id(new_id) into resource;
|
||||
end;
|
||||
$$;
|
||||
|
||||
-- drop procedure if exists insert_user(inout json);
|
||||
@@ -1,2 +0,0 @@
|
||||
-- User
|
||||
drop view if exists user_lite;
|
||||
@@ -1,5 +0,0 @@
|
||||
-- User
|
||||
create or replace view user_lite as
|
||||
select u.id, u.created_at, u.blocked_at, u.username
|
||||
from "user" u
|
||||
where u.blocked_at is null;
|
||||
@@ -1,26 +0,0 @@
|
||||
package fr.dcproject
|
||||
|
||||
import fr.postgresjson.connexion.Requester
|
||||
import io.ktor.util.KtorExperimentalAPI
|
||||
import org.koin.dsl.module
|
||||
import java.io.File
|
||||
import fr.dcproject.repository.Article as ArticleRepository
|
||||
|
||||
val config = Config()
|
||||
|
||||
@KtorExperimentalAPI
|
||||
val Module = module {
|
||||
|
||||
single { config }
|
||||
|
||||
single { Requester.RequesterFactory(
|
||||
host = config.host,
|
||||
database = config.database,
|
||||
username = config.username,
|
||||
password = config.password,
|
||||
port = config.port,
|
||||
functionsDirectory = File(this::class.java.getResource("/sql/functions").toURI())
|
||||
).createRequester() }
|
||||
|
||||
single { ArticleRepository(get<Requester>()) }
|
||||
}
|
||||
@@ -52,8 +52,8 @@ fun Application.module() {
|
||||
convert<Article> {
|
||||
decode { values, _ ->
|
||||
val id = values.singleOrNull()?.let { UUID.fromString(it) }
|
||||
?: throw InternalError("Cannot convert $values to Article")
|
||||
get<RepositoryArticle>().findById(id)
|
||||
?: throw InternalError("Cannot convert $values to UUID")
|
||||
get<RepositoryArticle>().findById(id) ?: throw InternalError("Article $values not found")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,16 @@
|
||||
package fr.dcproject
|
||||
|
||||
import com.typesafe.config.ConfigFactory
|
||||
import java.io.File
|
||||
|
||||
class Config {
|
||||
private var config = ConfigFactory.load()
|
||||
val sqlFiles = File(this::class.java.getResource("/sql").toURI())
|
||||
val envName: String = config.getString("app.envName")
|
||||
|
||||
val host: String = config.getString("db.host")
|
||||
val database: String = config.getString("db.database")
|
||||
val username: String = config.getString("db.username")
|
||||
val password: String = config.getString("db.password")
|
||||
var database: String = config.getString("db.database")
|
||||
var username: String = config.getString("db.username")
|
||||
var password: String = config.getString("db.password")
|
||||
val port: Int = config.getInt("db.port")
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package fr.dcproject
|
||||
|
||||
import fr.postgresjson.connexion.Connection
|
||||
import fr.postgresjson.connexion.Requester
|
||||
import fr.postgresjson.migration.Migrations
|
||||
import io.ktor.util.KtorExperimentalAPI
|
||||
import org.koin.dsl.module
|
||||
import fr.dcproject.repository.Article as ArticleRepository
|
||||
|
||||
val config = Config()
|
||||
|
||||
@KtorExperimentalAPI
|
||||
val Module = module {
|
||||
|
||||
single { config }
|
||||
|
||||
single { Connection(host = config.host, port = config.port, database = config.database, username = config.username, password = config.password) }
|
||||
|
||||
single { Requester.RequesterFactory(
|
||||
connection = get(),
|
||||
functionsDirectory = config.sqlFiles.resolve("functions")
|
||||
).createRequester() }
|
||||
|
||||
single { ArticleRepository(get()) }
|
||||
single { Migrations(connection = get(), directory = config.sqlFiles) }
|
||||
}
|
||||
File renamed without changes.
@@ -3,22 +3,23 @@ package fr.dcproject.entity
|
||||
import fr.postgresjson.entity.EntityCreatedAt
|
||||
import fr.postgresjson.entity.EntityCreatedAtImp
|
||||
import fr.postgresjson.entity.UuidEntity
|
||||
import org.joda.time.DateTime
|
||||
import java.util.*
|
||||
|
||||
|
||||
class Citizen(
|
||||
id: UUID?,
|
||||
id: UUID = UUID.randomUUID(),
|
||||
var name: Name?,
|
||||
var birthday: String?,
|
||||
var userId: String?,
|
||||
var voteAnnonymous: Boolean?,
|
||||
var followAnnonymous: Boolean?,
|
||||
var birthday: DateTime?,
|
||||
var userId: String? = null,
|
||||
var voteAnnonymous: Boolean? = null,
|
||||
var followAnnonymous: Boolean? = null,
|
||||
var user: User?
|
||||
) : UuidEntity(id),
|
||||
EntityCreatedAt by EntityCreatedAtImp() {
|
||||
data class Name(
|
||||
var civility: String?,
|
||||
var firstName: String?,
|
||||
var lastName: String?,
|
||||
var firstName: String?
|
||||
var civility: String? = null
|
||||
)
|
||||
}
|
||||
@@ -5,11 +5,10 @@ import org.joda.time.DateTime
|
||||
import java.util.*
|
||||
|
||||
class User(
|
||||
id: UUID?,
|
||||
id: UUID? = UUID.randomUUID(),
|
||||
var username: String?,
|
||||
var blockedAt: DateTime?,
|
||||
override var createdAt: DateTime?,
|
||||
override var updatedAt: DateTime?
|
||||
var blockedAt: DateTime? = null,
|
||||
var plainPassword: String?
|
||||
) : UuidEntity(id),
|
||||
EntityCreatedAt by EntityCreatedAtImp(),
|
||||
EntityUpdatedAt by EntityUpdatedAtImp()
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+2
-2
@@ -1,4 +1,4 @@
|
||||
create or replace procedure upsert_citizen(inout resource json)
|
||||
create or replace function upsert_citizen(inout resource json)
|
||||
language plpgsql as
|
||||
$$
|
||||
declare
|
||||
@@ -25,4 +25,4 @@ begin
|
||||
end;
|
||||
$$;
|
||||
|
||||
-- drop procedure if exists insert_user(inout json);
|
||||
-- drop function if exists upsert_citizen(inout json);
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,19 @@
|
||||
create or replace function insert_user(inout resource json) language plpgsql as
|
||||
$$
|
||||
declare
|
||||
new_id uuid;
|
||||
begin
|
||||
insert into "user" (id, username, password, blocked_at)
|
||||
select
|
||||
coalesce(t.id, uuid_generate_v4()),
|
||||
t.username,
|
||||
crypt(resource->>'plain_password', gen_salt('bf', 8)),
|
||||
case when t.blocked_at is not null then now() else null end
|
||||
from json_populate_record(null::"user", resource) t
|
||||
returning id into new_id;
|
||||
|
||||
select find_user_by_id(new_id) into resource;
|
||||
end;
|
||||
$$;
|
||||
|
||||
-- drop function if exists insert_user(inout json);
|
||||
File renamed without changes.
File renamed without changes.
-2
@@ -1,6 +1,4 @@
|
||||
-- Users
|
||||
create extension if not exists pgcrypto;
|
||||
|
||||
create table "user"
|
||||
(
|
||||
id uuid default uuid_generate_v4() not null primary key,
|
||||
@@ -9,7 +9,7 @@ declare
|
||||
selected_article json;
|
||||
begin
|
||||
-- insert user for context
|
||||
call insert_user(created_user);
|
||||
select insert_user(created_user) into created_user;
|
||||
_user_id := created_user->>'id';
|
||||
created_citizen := jsonb_set(created_citizen::jsonb, '{user}'::text[], jsonb_build_object('id', _user_id::text), true)::json;
|
||||
assert created_citizen#>>'{user, id}' = _user_id::text, format('userId in citizen must be the same as user, %s = %s', created_citizen#>>'{user, id}', _user_id::text);
|
||||
@@ -8,7 +8,7 @@ declare
|
||||
selected_citizen json;
|
||||
begin
|
||||
-- insert user for context
|
||||
call insert_user(created_user);
|
||||
select insert_user(created_user) into created_user;
|
||||
_user_id := created_user->>'id';
|
||||
created_citizen := jsonb_set(created_citizen::jsonb, '{user}'::text[], jsonb_build_object('id', _user_id::text), true)::json;
|
||||
assert created_citizen#>>'{user, id}' = _user_id::text, format('userId in citizen must be the same as user, %s = %s', created_citizen#>>'{user, id}', _user_id::text);
|
||||
@@ -28,8 +28,8 @@ declare
|
||||
_comment_id uuid;
|
||||
begin
|
||||
-- insert user for context
|
||||
call insert_user(created_user);
|
||||
call insert_user(created_user2);
|
||||
select insert_user(created_user) into created_user;
|
||||
select insert_user(created_user2) into created_user2;
|
||||
created_citizen := jsonb_set(created_citizen::jsonb, '{user}'::text[], jsonb_build_object('id', created_user->>'id'), true)::json;
|
||||
|
||||
-- insert new citizen for context
|
||||
+1
-1
@@ -42,7 +42,7 @@ declare
|
||||
$json$;
|
||||
begin
|
||||
-- insert user for context
|
||||
call insert_user(created_user);
|
||||
select insert_user(created_user) into created_user;
|
||||
_user_id := created_user->>'id';
|
||||
created_citizen := jsonb_set(created_citizen::jsonb, '{user}'::text[], jsonb_build_object('id', _user_id::text), true)::json;
|
||||
assert created_citizen#>>'{user, id}' = _user_id::text, format('userId in citizen must be the same as user, %s = %s', created_citizen#>>'{user, id}', _user_id::text);
|
||||
@@ -25,8 +25,8 @@ declare
|
||||
$json$;
|
||||
begin
|
||||
-- insert user for context
|
||||
call insert_user(created_user);
|
||||
call insert_user(created_user2);
|
||||
select insert_user(created_user) into created_user;
|
||||
select insert_user(created_user2) into created_user2;
|
||||
created_citizen := jsonb_set(created_citizen::jsonb, '{user}'::text[], jsonb_build_object('id', created_user->>'id'), true)::json;
|
||||
created_citizen2 := jsonb_set(created_citizen2::jsonb, '{user}'::text[], jsonb_build_object('id', created_user2->>'id'), true)::json;
|
||||
|
||||
@@ -6,7 +6,7 @@ declare
|
||||
exist_user json;
|
||||
begin
|
||||
-- Insert user and check if username and password is correct
|
||||
call insert_user(created_user);
|
||||
select insert_user(created_user) into created_user;
|
||||
assert created_user->>'username' = 'george', 'username must be george';
|
||||
assert created_user->>'password' is null, 'password must not be returned';
|
||||
|
||||
@@ -26,7 +26,7 @@ declare
|
||||
$json$;
|
||||
begin
|
||||
-- insert user for context
|
||||
call insert_user(created_user);
|
||||
select insert_user(created_user) into created_user;
|
||||
created_citizen := jsonb_set(created_citizen::jsonb, '{user}'::text[], jsonb_build_object('id', created_user->>'id'), true)::json;
|
||||
|
||||
-- insert new citizen for context
|
||||
@@ -1,17 +1,51 @@
|
||||
package fr.dcproject
|
||||
|
||||
import fr.postgresjson.migration.Migrations
|
||||
import io.ktor.http.ContentType
|
||||
import io.ktor.http.HttpHeaders
|
||||
import io.ktor.http.HttpMethod
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||
import io.ktor.server.testing.handleRequest
|
||||
import io.ktor.server.testing.setBody
|
||||
import io.ktor.server.testing.withTestApplication
|
||||
import kotlin.test.Test
|
||||
import io.ktor.util.KtorExperimentalAPI
|
||||
import org.junit.jupiter.api.AfterEach
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
import org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS
|
||||
import org.koin.core.context.startKoin
|
||||
import org.koin.core.context.stopKoin
|
||||
import org.koin.test.KoinTest
|
||||
import org.koin.test.inject
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
class ArticleRouteTest {
|
||||
@KtorExperimentalLocationsAPI
|
||||
@KtorExperimentalAPI
|
||||
@TestInstance(PER_CLASS)
|
||||
class ArticleRouteTest: KoinTest {
|
||||
private val migrations: Migrations by inject()
|
||||
|
||||
@BeforeEach
|
||||
fun beforeAll() {
|
||||
startKoin {
|
||||
modules(Module)
|
||||
config.database = "test"
|
||||
config.username = "test"
|
||||
config.password = "test"
|
||||
|
||||
}
|
||||
migrations.run()
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
fun afterAll() {
|
||||
migrations.forceAllDown()
|
||||
stopKoin()
|
||||
}
|
||||
|
||||
private val article: String = """{
|
||||
"id" : "8e8dd0aa-2b2b-41e1-bff5-ea613c988774",
|
||||
"version_id" : "e3ec9ea8-87ac-46ac-8321-8f2bc8c687bc",
|
||||
@@ -39,7 +73,7 @@ class ArticleRouteTest {
|
||||
}"""
|
||||
|
||||
@Test
|
||||
fun testRoot() {
|
||||
fun testRoute() {
|
||||
withTestApplication({ module() }) {
|
||||
handleRequest(HttpMethod.Get, "/articles").apply {
|
||||
assertEquals(HttpStatusCode.OK, response.status())
|
||||
@@ -3,22 +3,32 @@ import cucumber.api.Scenario
|
||||
import cucumber.api.java8.En
|
||||
import cucumber.api.junit.Cucumber
|
||||
import feature.Context
|
||||
import fr.dcproject.config
|
||||
import fr.postgresjson.migration.Migrations
|
||||
import io.ktor.server.testing.TestApplicationEngine
|
||||
import io.ktor.server.testing.createTestEnvironment
|
||||
import org.junit.runner.RunWith
|
||||
import org.koin.test.KoinTest
|
||||
import org.koin.test.inject
|
||||
import java.util.concurrent.TimeUnit
|
||||
import feature.Context.Companion.current as contextCurrent
|
||||
|
||||
@RunWith(Cucumber::class)
|
||||
@CucumberOptions(plugin = ["pretty"])
|
||||
class RunCucumberTest: En {
|
||||
class RunCucumberTest: En, KoinTest {
|
||||
private val migrations: Migrations by inject()
|
||||
init {
|
||||
Before(-1) { scenario: Scenario ->
|
||||
// config.database = "dc-projectg-test"
|
||||
config.database = "test"
|
||||
config.username = "test"
|
||||
config.password = "test"
|
||||
contextCurrent = Context(TestApplicationEngine(createTestEnvironment()) {}, scenario)
|
||||
|
||||
migrations.run()
|
||||
}
|
||||
|
||||
After { scenario: Scenario ->
|
||||
migrations.forceAllDown()
|
||||
contextCurrent.engine.stop(0L, 0L, TimeUnit.MILLISECONDS)
|
||||
}
|
||||
}
|
||||
@@ -3,10 +3,14 @@ package feature
|
||||
import cucumber.api.Scenario
|
||||
import fr.dcproject.module
|
||||
import io.ktor.application.Application
|
||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||
import io.ktor.server.testing.TestApplicationCall
|
||||
import io.ktor.server.testing.TestApplicationEngine
|
||||
import io.ktor.server.testing.TestApplicationRequest
|
||||
import io.ktor.util.KtorExperimentalAPI
|
||||
|
||||
@KtorExperimentalLocationsAPI
|
||||
@KtorExperimentalAPI
|
||||
class Context(
|
||||
val engine: TestApplicationEngine,
|
||||
val scenario: Scenario
|
||||
@@ -1,8 +1,11 @@
|
||||
package feature
|
||||
|
||||
import com.google.gson.Gson
|
||||
import cucumber.api.Scenario
|
||||
import cucumber.api.java8.En
|
||||
import fr.dcproject.entity.Citizen
|
||||
import fr.dcproject.entity.User
|
||||
import fr.postgresjson.connexion.Requester
|
||||
import fr.postgresjson.migration.Migrations
|
||||
import io.cucumber.datatable.DataTable
|
||||
import io.ktor.http.ContentType
|
||||
import io.ktor.http.HttpHeaders
|
||||
@@ -11,18 +14,46 @@ import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.server.testing.TestApplicationCall
|
||||
import io.ktor.server.testing.TestApplicationEngine
|
||||
import io.ktor.server.testing.setBody
|
||||
import org.joda.time.DateTime
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.koin.test.KoinTest
|
||||
import org.koin.test.inject
|
||||
import org.opentest4j.AssertionFailedError
|
||||
import java.util.*
|
||||
import kotlin.test.asserter
|
||||
import feature.Context.Companion.current as currentContext
|
||||
|
||||
class Request: En, KoinTest {
|
||||
private val migrations: Migrations by inject()
|
||||
private val requester: Requester by inject()
|
||||
init {
|
||||
Before { scenario: Scenario ->
|
||||
}
|
||||
// Before { scenario: Scenario ->
|
||||
// migrations.run()
|
||||
// }
|
||||
//
|
||||
// After { scenario: Scenario ->
|
||||
// migrations.forceAllDown()
|
||||
// }
|
||||
|
||||
After { scenario: Scenario ->
|
||||
When("I have citizen:") { body: DataTable ->
|
||||
val user = User(username = "jaque", plainPassword = "azerty")
|
||||
val data = body.asMap<String, String>(String::class.java, String::class.java)
|
||||
val citizen = Citizen(
|
||||
id = UUID.fromString(data["id"]),
|
||||
name = Citizen.Name(data["firstName"], data["lastName"]),
|
||||
birthday = DateTime.now(),
|
||||
user = user
|
||||
)
|
||||
val test: TestApplicationEngine.() -> Unit = {
|
||||
requester
|
||||
.getFunction("insert_user")
|
||||
.selectOne(user)
|
||||
requester
|
||||
.getFunction("upsert_citizen")
|
||||
.selectOne(citizen)
|
||||
}
|
||||
|
||||
currentContext.engine.test()
|
||||
}
|
||||
|
||||
When("I send a {string} request to {string} with body:") { method: String, uri: String, body: String ->
|
||||
@@ -55,7 +86,7 @@ class Request: En, KoinTest {
|
||||
Then("the response status code should be {int}") { statusCode: Int ->
|
||||
val call: TestApplicationCall = currentContext.call ?: throw AssertionFailedError("No call", statusCode, null)
|
||||
with(call) {
|
||||
assertEquals(HttpStatusCode.fromValue(statusCode), response.status())
|
||||
assertEquals(HttpStatusCode.fromValue(statusCode), response.status(), response.content)
|
||||
}
|
||||
}
|
||||
|
||||
+8
-9
@@ -4,11 +4,15 @@ Feature: articles routes
|
||||
When I send a "GET" request to "/articles"
|
||||
Then the response status code should be 200
|
||||
|
||||
Scenario: The route for get article must response a 200
|
||||
When I send a "GET" request to "/articles/55a24426-139b-4ee7-b1e2-a3d016d66cc2"
|
||||
Then the response status code should be 200
|
||||
# Scenario: The route for get article must response a 200
|
||||
# When I send a "GET" request to "/articles/55a24426-139b-4ee7-b1e2-a3d016d66cc2"
|
||||
# Then the response status code should be 200
|
||||
|
||||
Scenario: The route for get article must response a 200
|
||||
Given I have citizen:
|
||||
| id | 64b7b379-2298-43ec-b428-ba134930cabd |
|
||||
| firstName | Jaque |
|
||||
| lastName | Dupuis |
|
||||
When I send a "POST" request to "/articles" with body:
|
||||
"""
|
||||
{
|
||||
@@ -28,9 +32,4 @@ Feature: articles routes
|
||||
Then the response status code should be 200
|
||||
And the response should contain object:
|
||||
| version_id | 09c418b6-63ba-448b-b38b-502b41cd500e |
|
||||
| title | title2 |
|
||||
When I send a "GET" request to "/articles/99afd1b1-3555-43c1-80a7-63c56e93d250"
|
||||
Then the response status code should be 200
|
||||
And the response should contain object:
|
||||
| id | 99afd1b1-3555-43c1-80a7-63c56e93d250 |
|
||||
| title | title2 |
|
||||
| title | title2 |
|
||||
Reference in new issue
Block a user