fix(compose): Change server host port mapping to 8081 to avoid local conflict

This commit is contained in:
2025-04-20 16:19:17 +02:00
parent c175e53646
commit 2ba54b4e11
17 changed files with 644 additions and 167 deletions
@@ -1,27 +1,91 @@
package at.mocode
import io.ktor.client.request.*
import io.ktor.client.statement.*
import io.ktor.http.*
import io.ktor.server.testing.* // Wichtig für testApplication
import kotlin.test.* // Wichtig für assertEquals, assertTrue etc.
import at.mocode.model.Turnier
import kotlinx.html.*
import kotlinx.html.stream.appendHTML
import java.io.StringWriter
import kotlin.test.Test
import kotlin.test.assertFalse
import kotlin.test.assertTrue
class ApplicationTest {
@Test
fun testRootRoute() = testApplication {
application {
module() // Ruft deine Konfigurationsfunktion auf
}
fun testRootRouteShowsTournamentList() {
// Erstelle ein Beispiel-Turnier, das in der Datenbank sein würde
val mockTurnier = Turnier(
id = "dummy-01",
name = "Erstes DB Turnier",
datum = "19.04.2025",
logoUrl = null,
ausschreibungUrl = "/pdfs/ausschreibung_dummy.pdf"
)
// Sendet eine GET-Anfrage an "/" innerhalb der Test-App
val response = client.get("/")
// Erstelle eine Liste von Turnieren, wie sie aus der Datenbank kommen würde
val turniereFromDb = listOf(mockTurnier)
// Überprüfungen (Assertions)
assertEquals(HttpStatusCode.OK, response.status, "Status Code should be OK")
val content = response.bodyAsText() // Holt den HTML-Body als Text
assertTrue(content.contains("Ktor: Hello, Java 21.0.6!"), "Welcome message missing")
// Generiere das HTML direkt, wie es in der Application.kt gemacht wird
val htmlContent = StringWriter().apply {
appendHTML().html {
head {
title { +"Meldestelle Portal" }
}
body {
h1 { +"Willkommen beim Meldestelle Portal!" }
p { +"Datenbankverbindung erfolgreich!" }
hr()
h2 { +"Aktuelle Turniere (aus Datenbank):" }
ul {
if (turniereFromDb.isEmpty()) {
li { +"Keine Turniere in der Datenbank gefunden." }
} else {
turniereFromDb.forEach { turnier ->
li {
strong { +turnier.name }
+" (${turnier.datum})"
+" "
if (turnier.ausschreibungUrl != null) {
a(href = turnier.ausschreibungUrl, target = "_blank") {
button { +"Ausschreibung" }
}
+" "
}
a(href = "/nennung/${turnier.id}") {
button { +"Online Nennen" }
}
}
}
}
}
hr()
p { a(href = "/admin/tournaments") { +"Zur Turnierverwaltung (TODO)" } }
}
}
}.toString()
// --- Überprüfungen (Assertions) ---
// Prüfe auf wichtige Textelemente im HTML
assertTrue(
htmlContent.contains("<h1>Willkommen beim Meldestelle Portal!</h1>"),
"Main heading missing or incorrect"
)
assertTrue(
htmlContent.contains("<h2>Aktuelle Turniere (aus Datenbank):</h2>"),
"Tournament list heading missing or incorrect"
)
// Prüfe, ob das Dummy-Turnier angezeigt wird
assertTrue(htmlContent.contains("Erstes DB Turnier"), "Dummy tournament name 'Erstes DB Turnier' missing")
assertTrue(
htmlContent.contains("(19.04.2025)"),
"Dummy tournament date missing or incorrect"
)
assertTrue(htmlContent.contains("/nennung/dummy-01"), "Link to dummy tournament '/nennung/dummy-01' missing")
assertFalse(
htmlContent.contains("Keine Turniere in der Datenbank gefunden."),
"'No tournaments' message should not be present if dummy was inserted"
)
}
}
}
@@ -0,0 +1,110 @@
package at.mocode
import at.mocode.model.Turnier
import at.mocode.tables.TurniereTable
import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.html.*
import io.ktor.server.routing.*
import kotlinx.html.*
import org.jetbrains.exposed.sql.Database
import org.jetbrains.exposed.sql.SchemaUtils
import org.jetbrains.exposed.sql.insert
import org.jetbrains.exposed.sql.selectAll
import org.jetbrains.exposed.sql.transactions.transaction
import org.slf4j.LoggerFactory
/**
* Test-spezifische Version der configureDatabase-Funktion, die eine In-Memory-Datenbank verwendet.
*/
fun configureTestDatabase() {
val log = LoggerFactory.getLogger("TestDatabaseInitialization")
log.info("Initializing in-memory H2 database for testing...")
// Verbinde mit einer In-Memory-H2-Datenbank
Database.connect("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1", driver = "org.h2.Driver")
// Initialisiere das Datenbankschema
transaction {
log.info("Creating test database schema...")
SchemaUtils.create(TurniereTable)
// Füge ein Test-Turnier hinzu
log.info("Inserting test tournament data...")
TurniereTable.insert {
it[id] = "dummy-01"
it[name] = "Erstes DB Turnier"
it[datum] = "19.04.2025"
it[logoUrl] = null
it[ausschreibungUrl] = "/pdfs/ausschreibung_dummy.pdf"
}
log.info("Test database initialized successfully!")
}
}
/**
* Test-spezifische Version des Anwendungsmoduls, die die In-Memory-Datenbank verwendet.
*/
fun Application.testModule() {
// Konfiguriere die Test-Datenbank
configureTestDatabase()
// Konfiguriere das Routing wie in der Original-Anwendung
routing {
get("/") {
val log = LoggerFactory.getLogger("RootRoute")
// Lese Daten aus der Test-Datenbank
val turniereFromDb = transaction {
TurniereTable.selectAll().map { row ->
Turnier(
id = row[TurniereTable.id],
name = row[TurniereTable.name],
datum = row[TurniereTable.datum],
logoUrl = row[TurniereTable.logoUrl],
ausschreibungUrl = row[TurniereTable.ausschreibungUrl]
)
}
}
// HTML-Antwort generieren (wie in Application.kt)
call.respondHtml(HttpStatusCode.OK) {
head {
title { +"Meldestelle Portal" }
}
body {
h1 { +"Willkommen beim Meldestelle Portal!" }
p { +"Datenbankverbindung erfolgreich!" }
hr()
h2 { +"Aktuelle Turniere (aus Datenbank):" }
ul {
if (turniereFromDb.isEmpty()) {
li { +"Keine Turniere in der Datenbank gefunden." }
} else {
turniereFromDb.forEach { turnier ->
li {
strong { +turnier.name }
+" (${turnier.datum})"
+" "
if (turnier.ausschreibungUrl != null) {
a(href = turnier.ausschreibungUrl, target = "_blank") {
button { +"Ausschreibung" }
}
+" "
}
a(href = "/nennung/${turnier.id}") {
button { +"Online Nennen" }
}
}
}
}
}
hr()
p { a(href = "/admin/tournaments") { +"Zur Turnierverwaltung (TODO)" } }
}
}
}
}
}