summaryrefslogtreecommitdiff
path: root/internal/render/render_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/render/render_test.go')
-rw-r--r--internal/render/render_test.go122
1 files changed, 120 insertions, 2 deletions
diff --git a/internal/render/render_test.go b/internal/render/render_test.go
index 484a45b..d06fc7b 100644
--- a/internal/render/render_test.go
+++ b/internal/render/render_test.go
@@ -27,7 +27,7 @@ func row(hour int, temp float64, code int, mm, pop float64) openmeteo.Row {
func testConfig() config.Config {
c := config.Default()
- c.Columns = []string{"hour", "temp", "feels", "conditions", "mm", "rain"}
+ c.Columns = []string{"hour", "temp", "feels", "conditions", "humidity", "mm", "rain"}
c.Graph = false
c.Icons = "none"
c.DisplayLang = "en"
@@ -255,7 +255,7 @@ func TestTableMinimumWidthIsKnown(t *testing.T) {
widest = w
}
}
- const documented = 34
+ const documented = 40
if widest != documented {
t.Fatalf("the default table now needs %d columns, not the documented %d; "+
"update the README if this is intended", widest, documented)
@@ -285,3 +285,121 @@ func TestChartAxisLabelsAreWholeOrAbsent(t *testing.T) {
}
}
}
+
+func customCfg() config.Config {
+ c := testConfig()
+ c.Columns = []string{"hour", "temp", "birch", "soil"}
+ c.Custom = map[string]config.CustomColumn{
+ "birch": {Source: "air", Field: "birch_pollen", Label: "brzoza", Decimals: 1},
+ "soil": {Source: "forecast", Field: "soil_temperature_0cm", Suffix: "°", Decimals: 0},
+ }
+ return c
+}
+
+func TestCustomColumnsRender(t *testing.T) {
+ r := row(12, 25, 3, 0, 0)
+ r.Vals[CustomKey("birch")] = 12.34
+ r.Vals["soil_temperature_0cm"] = 21.6
+
+ out := Render(view(r), customCfg(), 80, false)
+ if !strings.Contains(out, "brzoza") {
+ t.Errorf("the declared label must be the header:\n%s", out)
+ }
+ if !strings.Contains(out, "12.3") {
+ t.Errorf("decimals=1 should give 12.3:\n%s", out)
+ }
+ if !strings.Contains(out, "22°") {
+ t.Errorf("decimals=0 with a suffix should give 22°:\n%s", out)
+ }
+}
+
+// "No data" and "zero" are different claims, and for an allergen the difference
+// matters.
+func TestCustomColumnBlankWhenTheApiGaveNothing(t *testing.T) {
+ r := row(12, 25, 3, 0, 0) // no custom values set at all
+ out := Render(view(r), customCfg(), 80, false)
+ if strings.Contains(out, "0.0") {
+ t.Errorf("a missing value must render blank, not as zero:\n%s", out)
+ }
+ if !strings.Contains(out, "brzoza") {
+ t.Errorf("the column should still be present:\n%s", out)
+ }
+}
+
+// A custom column named after a built-in API field must not read that field's
+// value; the prefix is what keeps them apart.
+func TestCustomKeyDoesNotCollideWithApiFields(t *testing.T) {
+ if CustomKey("temperature_2m") == "temperature_2m" {
+ t.Fatal("custom values must be stored under a distinct key")
+ }
+ r := row(12, 25, 3, 0, 0) // temperature_2m = 25
+ cfg := testConfig()
+ cfg.Columns = []string{"hour", "mine"}
+ cfg.Custom = map[string]config.CustomColumn{
+ "mine": {Source: "air", Field: "temperature_2m", Decimals: 0},
+ }
+ if out := Render(view(r), cfg, 80, false); strings.Contains(out, "25") {
+ t.Errorf("the custom column picked up the built-in field's value:\n%s", out)
+ }
+}
+
+func TestCustomColumnWidthFromLabelWhenUnset(t *testing.T) {
+ cfg := testConfig()
+ cfg.Columns = []string{"hour", "verylongname"}
+ cfg.Custom = map[string]config.CustomColumn{
+ "verylongname": {Source: "air", Field: "f", Label: "verylongname"},
+ }
+ r := row(12, 25, 3, 0, 0)
+ r.Vals[CustomKey("verylongname")] = 1
+ out := Render(view(r), cfg, 80, false)
+ for _, l := range strings.Split(out, "\n") {
+ if strings.Contains(l, "verylongname") && DisplayWidth(l) < 12 {
+ t.Errorf("header was truncated: %q", l)
+ }
+ }
+}
+
+// A species the user named is shown even at zero: they named it because they
+// react to it, and "none today" is the answer they wanted.
+func TestNamedPollenSpeciesShownEvenAtZero(t *testing.T) {
+ cfg := testConfig()
+ cfg.Pollen = []string{"birch"}
+ cfg.PollenExplicit = true
+ v := view(row(12, 25, 3, 0, 0))
+ v.Pollen = map[string]float64{"birch": 0}
+
+ out := Render(v, cfg, 80, false)
+ if !strings.Contains(out, "birch") {
+ t.Errorf("a named species must appear even at zero:\n%s", out)
+ }
+}
+
+// With pollen=all nobody chose, so a line of six zeroes is noise.
+func TestPollenAllHidesAbsentSpecies(t *testing.T) {
+ cfg := testConfig()
+ cfg.Pollen = []string{"grass", "birch"}
+ cfg.PollenExplicit = false
+ v := view(row(12, 25, 3, 0, 0))
+ v.Pollen = map[string]float64{"grass": 12, "birch": 0}
+
+ out := Render(v, cfg, 80, false)
+ if !strings.Contains(out, "grass") {
+ t.Errorf("a present species must be shown:\n%s", out)
+ }
+ if strings.Contains(out, "birch") {
+ t.Errorf("an absent species must be dropped when nobody named it:\n%s", out)
+ }
+}
+
+// No species is privileged. Grass used to be special-cased, which forced it on
+// someone allergic to birch while hiding theirs.
+func TestNoSpeciesIsPrivileged(t *testing.T) {
+ cfg := testConfig()
+ cfg.PollenExplicit = false
+ v := view(row(12, 25, 3, 0, 0))
+ v.Pollen = map[string]float64{"grass": 0, "birch": 0}
+
+ if out := Render(v, cfg, 80, false); strings.Contains(out, "grass") {
+ t.Errorf("grass at zero must be dropped like any other species:\n%s", out)
+ }
+}