--- /dev/null
+package net.pterodactylus.rhynodge.filters.webpages.dasenbrook
+
+import java.time.LocalDate
+import java.time.format.DateTimeFormatter
+import java.time.format.FormatStyle
+import java.util.Locale
+import kotlinx.html.body
+import kotlinx.html.dom.createHTMLDocument
+import kotlinx.html.dom.serialize
+import kotlinx.html.h1
+import kotlinx.html.head
+import kotlinx.html.html
+import kotlinx.html.li
+import kotlinx.html.ol
+import kotlinx.html.title
+import net.pterodactylus.rhynodge.states.AbstractState
+
+data class VacationHomeState(val home: String, val vacancies: List<Vacancy>) : AbstractState(true) {
+
+ public override fun plainText() = """
+Vakanzen von $home:
+
+${vacancies.joinToString("\n") { (begin, end, length) -> "${begin.toGermanDate()} bis ${end.toGermanDate()} ($length Tage)" }}
+""".trimIndent()
+
+ public override fun htmlText() = createHTMLDocument().html {
+ head {
+ title { text("Vakanzen von $home") }
+ }
+ body {
+ h1 { text("Vakanzen von $home") }
+ ol {
+ vacancies.forEach {
+ li {
+ text("${it.begin.toGermanDate()} bis ${it.end.toGermanDate()} (${it.length} Tage)")
+ }
+ }
+ }
+ }
+ }.serialize()
+}
+
+data class Vacancy(val begin: LocalDate, val end: LocalDate, val length: Int = begin.datesUntil(end).count().toInt())
+
+private fun LocalDate.toGermanDate() =
+ format(DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL).localizedBy(Locale.GERMAN))
--- /dev/null
+package net.pterodactylus.rhynodge.filters.webpages.dasenbrook
+
+import java.time.LocalDate
+import java.time.Month.APRIL
+import java.time.Month.MAY
+import org.hamcrest.MatcherAssert.assertThat
+import org.hamcrest.Matchers.contains
+import org.hamcrest.Matchers.equalTo
+import org.jsoup.Jsoup
+import org.junit.jupiter.api.Test
+
+class VacationHomeStateTest {
+
+ @Test
+ fun `plain text shows list of vacancies`() {
+ assertThat(vacationHomeState.plainText(), equalTo("Vakanzen von Test Home:\n\nMontag, 20. April 2026 bis Samstag, 25. April 2026 (5 Tage)\nFreitag, 15. Mai 2026 bis Freitag, 22. Mai 2026 (7 Tage)"))
+ }
+
+ @Test
+ fun `html text shows list of vacancies`() {
+ val document = Jsoup.parse(vacationHomeState.htmlText())
+ assertThat(document.select("h1").text(), equalTo("Vakanzen von Test Home"))
+ assertThat(document.select("li").eachText(), contains(
+ "Montag, 20. April 2026 bis Samstag, 25. April 2026 (5 Tage)",
+ "Freitag, 15. Mai 2026 bis Freitag, 22. Mai 2026 (7 Tage)"
+ ))
+ }
+
+}
+
+private val vacationHomeState = VacationHomeState("Test Home", listOf(
+ Vacancy(LocalDate.of(2026, APRIL, 20), LocalDate.of(2026, APRIL, 25)),
+ Vacancy(LocalDate.of(2026, MAY, 15), LocalDate.of(2026, MAY, 22)),
+))