diff --git a/build.gradle b/build.gradle index 6c12759..f87c6b1 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,7 @@ buildscript { - ext.kotlin_version = '1.3.31' - ext.spring_boot_version = '2.1.5.RELEASE' + ext.kotlin_version = '1.3.41' + ext.spring_boot_version = '2.1.7.RELEASE' repositories { jcenter() @@ -19,15 +19,21 @@ apply plugin: 'kotlin-spring' apply plugin: 'org.springframework.boot' apply plugin: 'io.spring.dependency-management' +test { + useJUnitPlatform() +} + repositories { jcenter() } dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" - implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.2.1" + implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.2.2" implementation 'org.jsoup:jsoup:1.12.1' implementation 'org.springframework.boot:spring-boot-starter-web' + + testImplementation("org.junit.jupiter:junit-jupiter:5.5.1") } compileKotlin { diff --git a/src/main/kotlin/org/mosad/thecitadelofricks/hsoparser/MensaParser.kt b/src/main/kotlin/org/mosad/thecitadelofricks/hsoparser/MensaParser.kt index 5f8bed6..1ac05c8 100644 --- a/src/main/kotlin/org/mosad/thecitadelofricks/hsoparser/MensaParser.kt +++ b/src/main/kotlin/org/mosad/thecitadelofricks/hsoparser/MensaParser.kt @@ -23,6 +23,7 @@ package org.mosad.thecitadelofricks.hsoparser import org.jsoup.Jsoup +import org.jsoup.nodes.Document import org.mosad.thecitadelofricks.Meal import org.mosad.thecitadelofricks.MensaWeek import org.slf4j.LoggerFactory @@ -33,16 +34,33 @@ class MensaParser { var logger: org.slf4j.Logger = LoggerFactory.getLogger(MensaParser::class.java) /** - * returns the mensa menu for a week + * returns the mensa's menu for a week * @param mensaMenuURL the url to a mensa menu (swfr) - * @return the menu plan found at menuURL or null if the request was not successful + * @return the mensa's menu as MensaWeek found at menuURL or null if the request was not successful */ fun getMensaMenu(mensaMenuURL: String): MensaWeek? { - val mealWeekList = MensaWeek() - try { + return try { val menuHTML = Jsoup.connect(mensaMenuURL).timeout(15000).get() + parseMensaMenu(menuHTML) + } catch (ex: SocketTimeoutException) { + logger.warn("timeout from $mensaMenuURL, updating on next attempt!") + null + } catch (gex: Exception) { + logger.error("general MensaParser error", gex) + null + } + } - menuHTML.select("#speiseplan-tabs").select("div.tab-content").select("div.menu-tagesplan") + /** + * parse the mensa's menu from the html document + * @param htmlDoc the html document containing the menu + * @return the mensa's menu as MensaWeek + */ + fun parseMensaMenu(htmlDoc: Document): MensaWeek? { + val mealWeekList = MensaWeek() + + try { + htmlDoc.select("#speiseplan-tabs").select("div.tab-content").select("div.menu-tagesplan") .forEachIndexed { dayIndex, day -> val strDay = day.select("h3").text() @@ -56,11 +74,8 @@ class MensaParser { } } - } catch (ex: SocketTimeoutException) { - logger.warn("timeout from $mensaMenuURL, updating on next attempt!") - return null - } catch (gex: Exception) { - logger.error("general MensaParser error", gex) + } catch (pex: Exception) { + logger.error("error while parsing the html file", pex) return null } diff --git a/src/test/kotlin/org/mosad/thecitadelofricks/hsoparser/MensaParserTest.kt b/src/test/kotlin/org/mosad/thecitadelofricks/hsoparser/MensaParserTest.kt new file mode 100644 index 0000000..afd23b0 --- /dev/null +++ b/src/test/kotlin/org/mosad/thecitadelofricks/hsoparser/MensaParserTest.kt @@ -0,0 +1,44 @@ +package org.mosad.thecitadelofricks.hsoparser + +import org.jsoup.Jsoup +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.Test +import java.io.File + +internal class MensaParserTest { + private val mensaMenuURL = "https://www.swfr.de/de/essen-trinken/speiseplaene/mensa-offenburg/" + + @Test + fun parseMensaMenuNormalWeek() { + val htmlFile = File(MensaParserTest::class.java.getResource("/html/Mensa_normal-week.html").path) + val htmlDoc = Jsoup.parse(htmlFile,"UTF-8", "https://www.swfr.de/") + val mensaWeek = MensaParser().parseMensaMenu(htmlDoc) + + // maybe we can find another way for the comparison + Assertions.assertEquals( + "MensaWeek(days=[Meals(meals=[Meal(day=Montag 03.07., heading=Essen 1, parts=[Gemüseauflauf , Frischkäse-Paprikasauce , Blattsalat Kennzeichnungen/Zusatzstoffe: 9 Kennzeichnungen/Zusatzstoffe: 9, enthält Allergene: Ei,ML,Lak], additives=Kennzeichnungen/Zusatzstoffe: 9 enthält Allergene: Ei,ML,Lak), Meal(day=Montag 03.07., heading=Essen 2, parts=[Schweinesteak , Pfeffer-Rahmsauce , Country Potatoes , Blattsalat Kennzeichnungen/Zusatzstoffe: 1,5 Kennzeichnungen/Zusatzstoffe: 1,5, enthält Allergene: Gl,GlW,GlG,ML,Lak], additives=Kennzeichnungen/Zusatzstoffe: 1,5 enthält Allergene: Gl,GlW,GlG,ML,Lak), Meal(day=Montag 03.07., heading=Buffet, parts=[Grill und Salatbar , Asiatisches aus dem Wok , Fleisch- und Fischspezialitäten , Pasta-, Reis und Kartoffelvariationen , Gemüse], additives=)]), Meals(meals=[Meal(day=Dienstag 04.07., heading=Essen 1, parts=[Riesenrösti , Rahmchampignons , Blattsalat enthält Allergene: Gl,GlW,GlG,ML,Lak], additives=enthält Allergene: Gl,GlW,GlG,ML,Lak), Meal(day=Dienstag 04.07., heading=Essen 2, parts=[Spaghetti , Sauce Bolognese , Geriebener Hartkäse , Blattsalat Kennzeichnungen/Zusatzstoffe: 15 Kennzeichnungen/Zusatzstoffe: 15, enthält Allergene: Ei,Se,Gl,GlW,ML], additives=Kennzeichnungen/Zusatzstoffe: 15 enthält Allergene: Ei,Se,Gl,GlW,ML), Meal(day=Dienstag 04.07., heading=Buffet, parts=[Grill und Salatbar , Asiatisches aus dem Wok , Fleisch- und Fischspezialitäten , Pasta-, Reis und Kartoffelvariationen , Gemüse], additives=)]), Meals(meals=[Meal(day=Mittwoch 05.07., heading=Essen 1, parts=[Frühlingsrollen , Feuriger Chilidip , Patnareis , Wokgemüsepfanne Kennzeichnungen/Zusatzstoffe: 9 Kennzeichnungen/Zusatzstoffe: 9, enthält Allergene: Ei,So,Sn,Se,Sf,Gl,GlW,ML,Lak], additives=Kennzeichnungen/Zusatzstoffe: 9 enthält Allergene: Ei,So,Sn,Se,Sf,Gl,GlW,ML,Lak), Meal(day=Mittwoch 05.07., heading=Essen 2, parts=[Bratwurstschnecke , Bratenjus , Kartoffelbrei , Karottengemüse Kennzeichnungen/Zusatzstoffe: 1,8 Kennzeichnungen/Zusatzstoffe: 1,8, enthält Allergene: Sn,Se,Gl,GlW,GlG,ML,Lak], additives=Kennzeichnungen/Zusatzstoffe: 1,8 enthält Allergene: Sn,Se,Gl,GlW,GlG,ML,Lak), Meal(day=Mittwoch 05.07., heading=Buffet, parts=[Grill und Salatbar , Asiatisches aus dem Wok , Fleisch- und Fischspezialitäten , Pasta-, Reis und Kartoffelvariationen , Gemüse], additives=)]), Meals(meals=[Meal(day=Donnerstag 06.07., heading=Essen 1, parts=[Farfalle tricolore , Gorgonzola-Spinatsauce , Endiviensalat enthält Allergene: Gl,GlW,ML], additives=enthält Allergene: Gl,GlW,ML), Meal(day=Donnerstag 06.07., heading=Essen 2, parts=[Paniertes Seelachsfilet MSC , Remouladensauce , Salzkartoffeln , Brokkoligemüse Kennzeichnungen/Zusatzstoffe: 9,MSC Kennzeichnungen/Zusatzstoffe: 9,MSC, enthält Allergene: Ei,Sn,Fi,Gl,GlW,ML,Lak], additives=Kennzeichnungen/Zusatzstoffe: 9,MSC enthält Allergene: Ei,Sn,Fi,Gl,GlW,ML,Lak), Meal(day=Donnerstag 06.07., heading=Buffet, parts=[Grill und Salatbar , Asiatisches aus dem Wok , Fleisch- und Fischspezialitäten , Pasta-, Reis und Kartoffelvariationen , Gemüse], additives=)]), Meals(meals=[Meal(day=Freitag 07.07., heading=Essen 1, parts=[Italienischer Nudelauflauf mit Gemüse , Tomatenragout , Blattsalat enthält Allergene: Gl,GlW,ML,Lak], additives=enthält Allergene: Gl,GlW,ML,Lak), Meal(day=Freitag 07.07., heading=Essen 2, parts=[Hähnchen-Saté-Spieß , Erdnusssauce , Langkornreis , Karotten-Erbsengemüse enthält Allergene: Er,So,Kr,Fi,We,Gl,GlW,ML,Lak], additives=enthält Allergene: Er,So,Kr,Fi,We,Gl,GlW,ML,Lak), Meal(day=Freitag 07.07., heading=Buffet, parts=[Grill und Salatbar , Asiatisches aus dem Wok , Fleisch- und Fischspezialitäten , Pasta-, Reis und Kartoffelvariationen , Gemüse], additives=)]), Meals(meals=[]), Meals(meals=[])])", + mensaWeek.toString() + ) + + } + + @Test + fun parseMensaMenuEmptyWeek() { + val htmlFile = File(MensaParserTest::class.java.getResource("/html/Mensa_empty-week.html").path) + val htmlDoc = Jsoup.parse(htmlFile,"UTF-8", "https://www.swfr.de/") + val mensaWeek = MensaParser().parseMensaMenu(htmlDoc) + + Assertions.assertEquals( + "MensaWeek(days=[Meals(meals=[]), Meals(meals=[]), Meals(meals=[]), Meals(meals=[]), Meals(meals=[]), Meals(meals=[]), Meals(meals=[])])", + mensaWeek.toString() + ) + } + + // TODO add test for special days ie. public holiday + + @Test + fun getMenuLinkNextWeek() { + val urlNextWeek = MensaParser().getMenuLinkNextWeek(mensaMenuURL) // this need a connection to the swfr server + Assertions.assertNotNull(urlNextWeek) + } +} \ No newline at end of file diff --git a/src/test/resources/html/Mensa_empty-week.html b/src/test/resources/html/Mensa_empty-week.html new file mode 100644 index 0000000..c736dd7 --- /dev/null +++ b/src/test/resources/html/Mensa_empty-week.html @@ -0,0 +1,134 @@ +
+
+
+ + +
+
+
+ + + + + + + + + + + + + + + +
vegetarisch
vegan
auf Wunsch vegan
+
+ + +
+
+ + + + + + +
+
diff --git a/src/test/resources/html/Mensa_normal-week.html b/src/test/resources/html/Mensa_normal-week.html new file mode 100644 index 0000000..9aa17f3 --- /dev/null +++ b/src/test/resources/html/Mensa_normal-week.html @@ -0,0 +1,518 @@ +
+
+
+ + +
+
+
+ + + + + + + + + + + + + + + +
vegetarisch
vegan
auf Wunsch vegan
+
+ + +
+
+ + + + + + +
+
+ +