fix: added new tests with gemini
This commit is contained in:
parent
17f04d71a4
commit
263f182bab
|
|
@ -1,14 +1,16 @@
|
||||||
package com.oliver.kidio.backend
|
package com.oliver.kidio.backend
|
||||||
|
|
||||||
|
import com.oliver.kidio.backend.domain.repository.InMemoryKidioRepository
|
||||||
|
import com.oliver.kidio.backend.plugins.configureRouting
|
||||||
|
import com.oliver.kidio.backend.plugins.configureSecurity
|
||||||
|
import com.oliver.kidio.backend.security.JwtService
|
||||||
import io.ktor.client.request.*
|
import io.ktor.client.request.*
|
||||||
import io.ktor.client.statement.*
|
import io.ktor.client.statement.*
|
||||||
import io.ktor.http.*
|
import io.ktor.http.*
|
||||||
import io.ktor.server.application.*
|
|
||||||
import io.ktor.server.testing.*
|
|
||||||
import com.oliver.kidio.backend.plugins.configureRouting
|
|
||||||
import com.oliver.kidio.backend.domain.repository.InMemoryKidioRepository
|
|
||||||
import io.ktor.server.plugins.contentnegotiation.ContentNegotiation as ServerContentNegotiation
|
|
||||||
import io.ktor.serialization.kotlinx.json.*
|
import io.ktor.serialization.kotlinx.json.*
|
||||||
|
import io.ktor.server.application.*
|
||||||
|
import io.ktor.server.plugins.contentnegotiation.ContentNegotiation as ServerContentNegotiation
|
||||||
|
import io.ktor.server.testing.*
|
||||||
import kotlinx.serialization.json.*
|
import kotlinx.serialization.json.*
|
||||||
import kotlin.test.*
|
import kotlin.test.*
|
||||||
|
|
||||||
|
|
@ -16,11 +18,15 @@ class ServerTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `test health endpoint`() = testApplication {
|
fun `test health endpoint`() = testApplication {
|
||||||
|
val jwtService = JwtService()
|
||||||
|
val repository = InMemoryKidioRepository()
|
||||||
|
|
||||||
application {
|
application {
|
||||||
this.install(ServerContentNegotiation) {
|
install(ServerContentNegotiation) {
|
||||||
json()
|
json()
|
||||||
}
|
}
|
||||||
configureRouting(InMemoryKidioRepository())
|
configureSecurity(jwtService)
|
||||||
|
configureRouting(repository, jwtService)
|
||||||
}
|
}
|
||||||
|
|
||||||
val response = client.get("/api/v1/health")
|
val response = client.get("/api/v1/health")
|
||||||
|
|
@ -29,16 +35,87 @@ class ServerTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `test tasks endpoint and verify`() = testApplication {
|
fun `test protected endpoints reject unauthorized requests`() = testApplication {
|
||||||
|
val jwtService = JwtService()
|
||||||
|
val repository = InMemoryKidioRepository()
|
||||||
|
|
||||||
application {
|
application {
|
||||||
this.install(ServerContentNegotiation) {
|
install(ServerContentNegotiation) {
|
||||||
json()
|
json()
|
||||||
}
|
}
|
||||||
configureRouting(InMemoryKidioRepository())
|
configureSecurity(jwtService)
|
||||||
|
configureRouting(repository, jwtService)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1. Get Tasks
|
// Ohne Token muss 401 Unauthorized kommen
|
||||||
val tasksResponse = client.get("/api/v1/tasks")
|
val tasksResponse = client.get("/api/v1/tasks")
|
||||||
|
assertEquals(HttpStatusCode.Unauthorized, tasksResponse.status)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test registration and login flow`() = testApplication {
|
||||||
|
val jwtService = JwtService()
|
||||||
|
val repository = InMemoryKidioRepository()
|
||||||
|
|
||||||
|
application {
|
||||||
|
install(ServerContentNegotiation) {
|
||||||
|
json()
|
||||||
|
}
|
||||||
|
configureSecurity(jwtService)
|
||||||
|
configureRouting(repository, jwtService)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. Registrierung
|
||||||
|
val registerResponse = client.post("/api/v1/auth/register") {
|
||||||
|
header(HttpHeaders.ContentType, ContentType.Application.Json.toString())
|
||||||
|
setBody(
|
||||||
|
"""{
|
||||||
|
"email": "test@family.de",
|
||||||
|
"passwordPlain": "strengGeheim1",
|
||||||
|
"familyName": "Familie Schmidt",
|
||||||
|
"childAge": 8,
|
||||||
|
"parentPin": "4321"
|
||||||
|
}"""
|
||||||
|
)
|
||||||
|
}
|
||||||
|
assertEquals(HttpStatusCode.Created, registerResponse.status)
|
||||||
|
assertTrue(registerResponse.bodyAsText().contains("token"))
|
||||||
|
|
||||||
|
// 2. Login mit denselben Daten
|
||||||
|
val loginResponse = client.post("/api/v1/auth/login") {
|
||||||
|
header(HttpHeaders.ContentType, ContentType.Application.Json.toString())
|
||||||
|
setBody(
|
||||||
|
"""{
|
||||||
|
"email": "test@family.de",
|
||||||
|
"passwordPlain": "strengGeheim1"
|
||||||
|
}"""
|
||||||
|
)
|
||||||
|
}
|
||||||
|
assertEquals(HttpStatusCode.OK, loginResponse.status)
|
||||||
|
val loginJson = Json.decodeFromString<AuthResponse>(loginResponse.bodyAsText())
|
||||||
|
assertNotNull(loginJson.token)
|
||||||
|
assertEquals("Familie Schmidt", loginJson.familyName)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test tasks endpoint and verify with jwt`() = testApplication {
|
||||||
|
val jwtService = JwtService()
|
||||||
|
val repository = InMemoryKidioRepository()
|
||||||
|
|
||||||
|
application {
|
||||||
|
install(ServerContentNegotiation) {
|
||||||
|
json()
|
||||||
|
}
|
||||||
|
configureSecurity(jwtService)
|
||||||
|
configureRouting(repository, jwtService)
|
||||||
|
}
|
||||||
|
|
||||||
|
val token = jwtService.generateToken("default_user")
|
||||||
|
|
||||||
|
// 1. Get Tasks mit Token
|
||||||
|
val tasksResponse = client.get("/api/v1/tasks") {
|
||||||
|
header(HttpHeaders.Authorization, "Bearer $token")
|
||||||
|
}
|
||||||
assertEquals(HttpStatusCode.OK, tasksResponse.status)
|
assertEquals(HttpStatusCode.OK, tasksResponse.status)
|
||||||
val tasksJson = Json.decodeFromString<List<Task>>(tasksResponse.bodyAsText())
|
val tasksJson = Json.decodeFromString<List<Task>>(tasksResponse.bodyAsText())
|
||||||
assertEquals(2, tasksJson.size)
|
assertEquals(2, tasksJson.size)
|
||||||
|
|
@ -47,6 +124,7 @@ class ServerTest {
|
||||||
|
|
||||||
// 2. Verify Task correct answer
|
// 2. Verify Task correct answer
|
||||||
val verifyResponse = client.post("/api/v1/tasks/verify") {
|
val verifyResponse = client.post("/api/v1/tasks/verify") {
|
||||||
|
header(HttpHeaders.Authorization, "Bearer $token")
|
||||||
header(HttpHeaders.ContentType, ContentType.Application.Json.toString())
|
header(HttpHeaders.ContentType, ContentType.Application.Json.toString())
|
||||||
setBody("""{"taskId":"t1","selectedAnswer":"27"}""")
|
setBody("""{"taskId":"t1","selectedAnswer":"27"}""")
|
||||||
}
|
}
|
||||||
|
|
@ -57,6 +135,7 @@ class ServerTest {
|
||||||
|
|
||||||
// 3. Verify Task incorrect answer
|
// 3. Verify Task incorrect answer
|
||||||
val verifyWrongResponse = client.post("/api/v1/tasks/verify") {
|
val verifyWrongResponse = client.post("/api/v1/tasks/verify") {
|
||||||
|
header(HttpHeaders.Authorization, "Bearer $token")
|
||||||
header(HttpHeaders.ContentType, ContentType.Application.Json.toString())
|
header(HttpHeaders.ContentType, ContentType.Application.Json.toString())
|
||||||
setBody("""{"taskId":"t1","selectedAnswer":"99"}""")
|
setBody("""{"taskId":"t1","selectedAnswer":"99"}""")
|
||||||
}
|
}
|
||||||
|
|
@ -67,16 +146,23 @@ class ServerTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `test screentime sync`() = testApplication {
|
fun `test screentime sync deducts time repeatedly`() = testApplication {
|
||||||
|
val jwtService = JwtService()
|
||||||
|
val repository = InMemoryKidioRepository()
|
||||||
|
|
||||||
application {
|
application {
|
||||||
this.install(ServerContentNegotiation) {
|
install(ServerContentNegotiation) {
|
||||||
json()
|
json()
|
||||||
}
|
}
|
||||||
configureRouting(InMemoryKidioRepository())
|
configureSecurity(jwtService)
|
||||||
|
configureRouting(repository, jwtService)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sync first time (user default_user has 1800s seeded)
|
val token = jwtService.generateToken("default_user")
|
||||||
|
|
||||||
|
// 1. Sync: 200 Sekunden abziehen (1800 -> 1600)
|
||||||
val syncResponse1 = client.post("/api/v1/screentime/sync") {
|
val syncResponse1 = client.post("/api/v1/screentime/sync") {
|
||||||
|
header(HttpHeaders.Authorization, "Bearer $token")
|
||||||
header(HttpHeaders.ContentType, ContentType.Application.Json.toString())
|
header(HttpHeaders.ContentType, ContentType.Application.Json.toString())
|
||||||
setBody("""{"userId":"default_user","usedSecondsSinceLastSync":200}""")
|
setBody("""{"userId":"default_user","usedSecondsSinceLastSync":200}""")
|
||||||
}
|
}
|
||||||
|
|
@ -85,14 +171,26 @@ class ServerTest {
|
||||||
assertEquals(1600, syncJson1.remainingSeconds)
|
assertEquals(1600, syncJson1.remainingSeconds)
|
||||||
assertFalse(syncJson1.isBlocked)
|
assertFalse(syncJson1.isBlocked)
|
||||||
|
|
||||||
// Sync and block
|
// 2. Erneuter Sync: Weitere 300 Sekunden abziehen (1600 -> 1300) - darf nicht auf 1800 zurückspringen!
|
||||||
val syncResponse2 = client.post("/api/v1/screentime/sync") {
|
val syncResponse2 = client.post("/api/v1/screentime/sync") {
|
||||||
|
header(HttpHeaders.Authorization, "Bearer $token")
|
||||||
header(HttpHeaders.ContentType, ContentType.Application.Json.toString())
|
header(HttpHeaders.ContentType, ContentType.Application.Json.toString())
|
||||||
setBody("""{"userId":"default_user","usedSecondsSinceLastSync":2000}""")
|
setBody("""{"userId":"default_user","usedSecondsSinceLastSync":300}""")
|
||||||
}
|
}
|
||||||
assertEquals(HttpStatusCode.OK, syncResponse2.status)
|
assertEquals(HttpStatusCode.OK, syncResponse2.status)
|
||||||
val syncJson2 = Json.decodeFromString<SyncResponse>(syncResponse2.bodyAsText())
|
val syncJson2 = Json.decodeFromString<SyncResponse>(syncResponse2.bodyAsText())
|
||||||
assertEquals(0, syncJson2.remainingSeconds)
|
assertEquals(1300, syncJson2.remainingSeconds)
|
||||||
assertTrue(syncJson2.isBlocked)
|
assertFalse(syncJson2.isBlocked)
|
||||||
|
|
||||||
|
// 3. Sync bis zur Sperre (weitere 1500 Sekunden abziehen -> 0)
|
||||||
|
val syncResponse3 = client.post("/api/v1/screentime/sync") {
|
||||||
|
header(HttpHeaders.Authorization, "Bearer $token")
|
||||||
|
header(HttpHeaders.ContentType, ContentType.Application.Json.toString())
|
||||||
|
setBody("""{"userId":"default_user","usedSecondsSinceLastSync":1500}""")
|
||||||
|
}
|
||||||
|
assertEquals(HttpStatusCode.OK, syncResponse3.status)
|
||||||
|
val syncJson3 = Json.decodeFromString<SyncResponse>(syncResponse3.bodyAsText())
|
||||||
|
assertEquals(0, syncJson3.remainingSeconds)
|
||||||
|
assertTrue(syncJson3.isBlocked)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue