diff options
Diffstat (limited to 'internal/render/render_test.go')
| -rw-r--r-- | internal/render/render_test.go | 122 |
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) + } +} |
