Show optional columns
authorDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Sun, 29 May 2016 19:00:15 +0000 (21:00 +0200)
committerDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Sun, 29 May 2016 19:00:15 +0000 (21:00 +0200)
src/main/kotlin/net/pterodactylus/rhynodge/webpages/weather/WeatherTrigger.kt
src/test/kotlin/net/pterodactylus/rhynodge/webpages/weather/WeatherTriggerTest.kt

index 4bc46d4..0522b02 100644 (file)
@@ -50,33 +50,59 @@ class WeatherTrigger : Trigger {
             head {
                 style("text/css") {
                     unsafe {
-                        +".hour-state { display: table-row; } "
-                        +".hour-state > div { display: table-cell; padding-right: 1em; } "
+                        +".weather-states { display: table; } "
+                        +".hour-state, .header { display: table-row; } "
+                        +".hour-state > div { display: table-cell; padding: 0em 0.5em; text-align: center; } "
+                        +".header > div { display: table-cell; padding: 0em 0.5em; font-weight: bold; text-align: center; } "
                     }
                 }
             }
             body {
                 val startTime = state.dateTime.toInstant()
                 h1 { +"The Weather (according to wetter.de) on %s".format(dateFormatter.format(startTime.toEpochMilli())) }
+                val showFeltTemperature = state.any { it.feltTemperature != null }
+                val showGustSpeed = state.any { it.gustSpeed != null }
+                val showHumidity = state.any { it.humidity != null }
                 state.forEach {
-                    div("hour-state") {
-                        div("time") { +"%tH:%<tM".format(startTime.plus(it.hourIndex.toLong(), ChronoUnit.HOURS).toEpochMilli()) }
-                        div("temperature") { +"%d °C".format(it.temperature) }
-                        it.feltTemperature?.let {
-                            div("felt-temperature") { +"(%d °C)".format(it) }
+                    div("weather-states") {
+                        div("header") {
+                            div { +"Time" }
+                            div { +"Temperature" }
+                            if (showHumidity) {
+                                div { +"feels like" }
+                            }
+                            div { +"Chance of Rain" }
+                            div { +"Amount" }
+                            div { +"Wind from" }
+                            div { +"Speed" }
+                            if (showGustSpeed) {
+                                div { +"Gusts" }
+                            }
+                            if (showHumidity) {
+                                div { +"Humidity" }
+                            }
+                            div { +"Description" }
+                            div { +"Image" }
                         }
-                        div("rain-probability") { +"%d%%".format((it.rainProbability * 100).toInt()) }
-                        div("rain-amount") { +"%s l/m²".format(it.rainAmount.minDigits()) }
-                        div("wind-direction") { +it.windDirection.arrow }
-                        div("wind-speed") { +"%d km/h".format(it.windSpeed) }
-                        it.gustSpeed?.let {
-                            div("gust-speed") { +"(up to %d km/h)".format(it) }
+                        div("hour-state") {
+                            div("time") { +"%tH:%<tM".format(startTime.plus(it.hourIndex.toLong(), ChronoUnit.HOURS).toEpochMilli()) }
+                            div("temperature") { +"%d °C".format(it.temperature) }
+                            if (showFeltTemperature) {
+                                div("felt-temperature") { +if (it.feltTemperature != null) "(${it.feltTemperature} °C)" else "" }
+                            }
+                            div("rain-probability") { +"%d%%".format((it.rainProbability * 100).toInt()) }
+                            div("rain-amount") { +"%s l/m²".format(it.rainAmount.minDigits()) }
+                            div("wind-direction") { +it.windDirection.arrow }
+                            div("wind-speed") { +"%d km/h".format(it.windSpeed) }
+                            if (showGustSpeed) {
+                                div("gust-speed") { +if (it.gustSpeed != null) "(up to ${it.gustSpeed} km/h)" else "" }
+                            }
+                            if (showHumidity) {
+                                div("humidity") { +if (it.humidity != null) "${it.humidity.times(100).toInt()}%" else "" }
+                            }
+                            div("description") { +it.description }
+                            div("image") { img(src = it.image) }
                         }
-                        it.humidity?.let {
-                            div("humidity") { +"%d%%".format((it * 100).toInt()) }
-                        }
-                        div("description") { +it.description }
-                        div("image") { img(src = it.image) }
                     }
                 }
             }
index 48dfe89..ee4b53b 100644 (file)
@@ -5,6 +5,7 @@ import net.pterodactylus.rhynodge.State
 import org.hamcrest.MatcherAssert.assertThat
 import org.hamcrest.Matchers.`is`
 import org.hamcrest.Matchers.containsString
+import org.hamcrest.Matchers.not
 import org.junit.Test
 import org.mockito.Mockito.mock
 import java.io.File
@@ -85,4 +86,48 @@ class WeatherTriggerTest {
         assertThat(htmlText, containsString("http://28"))
     }
 
+    @Test
+    fun outputContainsColumnHeadersForAllColumns() {
+        val currentState = WeatherState("Weather", ZonedDateTime.of(2016, 5, 28, 0, 0, 0, 0, of("Europe/Berlin")))
+        currentState += HourState(0, 10, 11, 0.12, 13.0, WindDirection.SOUTHSOUTHEAST, 14, 15, 0.16, "17", "http://18")
+        currentState += HourState(1, 20, 21, 0.22, 23.0, WindDirection.NORTHNORTHWEST, 24, 25, 0.26, "27", "http://28")
+        trigger.mergeStates(previousState, currentState)
+        val reaction = mock(Reaction::class.java)
+        val output = trigger.output(reaction)
+        val htmlText = output.text("text/html", -1)
+        assertThat(htmlText, containsString("Time"))
+        assertThat(htmlText, containsString("Temperature"))
+        assertThat(htmlText, containsString("feels like"))
+        assertThat(htmlText, containsString("Chance of Rain"))
+        assertThat(htmlText, containsString("Amount"))
+        assertThat(htmlText, containsString("Wind from"))
+        assertThat(htmlText, containsString("Speed"))
+        assertThat(htmlText, containsString("Gusts"))
+        assertThat(htmlText, containsString("Humidity"))
+        assertThat(htmlText, containsString("Description"))
+        assertThat(htmlText, containsString("Image"))
+    }
+
+    @Test
+    fun outputDoesNotContainColumnHeadersForMissingColumns() {
+        val currentState = WeatherState("Weather", ZonedDateTime.of(2016, 5, 28, 0, 0, 0, 0, of("Europe/Berlin")))
+        currentState += HourState(0, 10, null, 0.12, 13.0, WindDirection.SOUTHSOUTHEAST, 14, null, null, "17", "http://18")
+        currentState += HourState(1, 20, null, 0.22, 23.0, WindDirection.NORTHNORTHWEST, 24, null, null, "27", "http://28")
+        trigger.mergeStates(previousState, currentState)
+        val reaction = mock(Reaction::class.java)
+        val output = trigger.output(reaction)
+        val htmlText = output.text("text/html", -1)
+        assertThat(htmlText, containsString("Time"))
+        assertThat(htmlText, containsString("Temperature"))
+        assertThat(htmlText, not(containsString("feels like")))
+        assertThat(htmlText, containsString("Chance of Rain"))
+        assertThat(htmlText, containsString("Amount"))
+        assertThat(htmlText, containsString("Wind from"))
+        assertThat(htmlText, containsString("Speed"))
+        assertThat(htmlText, not(containsString("Gusts")))
+        assertThat(htmlText, not(containsString("Humidity")))
+        assertThat(htmlText, containsString("Description"))
+        assertThat(htmlText, containsString("Image"))
+    }
+
 }