diff options
Diffstat (limited to 'internal/config/config_test.go')
| -rw-r--r-- | internal/config/config_test.go | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/internal/config/config_test.go b/internal/config/config_test.go index 06c0234..46a8635 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -156,3 +156,126 @@ func TestWriteDefaultRoundTrips(t *testing.T) { t.Fatalf("the file we generate must validate: %v", err) } } + +func TestCustomColumnDeclaration(t *testing.T) { + cfg, err := Load(write(t, `columns=hour,temp,birch +column.birch = air:birch_pollen +label.birch = brzoza +width.birch = 7 +decimals.birch = 2 +suffix.birch = g +`)) + if err != nil { + t.Fatal(err) + } + cc, ok := cfg.Custom["birch"] + if !ok { + t.Fatal("birch was not declared") + } + if cc.Source != "air" || cc.Field != "birch_pollen" { + t.Errorf("source/field = %q/%q", cc.Source, cc.Field) + } + if cc.Label != "brzoza" || cc.Width != 7 || cc.Decimals != 2 || cc.Suffix != "g" { + t.Errorf("attributes not parsed: %+v", cc) + } + if err := cfg.Validate(); err != nil { + t.Fatalf("a complete declaration must validate: %v", err) + } +} + +// Only the fields a selected column needs, split by which API serves them. +func TestCustomColumnsSplitFieldsByApi(t *testing.T) { + cfg, err := Load(write(t, `columns=hour,temp,birch,soil +column.birch = air:birch_pollen +column.soil = forecast:soil_temperature_0cm +`)) + if err != nil { + t.Fatal(err) + } + fc := strings.Join(cfg.Fields(), ",") + if !strings.Contains(fc, "soil_temperature_0cm") || !strings.Contains(fc, "temperature_2m") { + t.Errorf("forecast fields = %q", fc) + } + if strings.Contains(fc, "birch_pollen") { + t.Errorf("an air field must not be asked of the forecast API: %q", fc) + } + if air := strings.Join(cfg.AirFields(), ","); air != "birch_pollen" { + t.Errorf("air fields = %q, want birch_pollen", air) + } +} + +// No custom air column means no second request at all. +func TestNoAirFieldsWhenNoneDeclared(t *testing.T) { + if got := Default().AirFields(); len(got) != 0 { + t.Fatalf("AirFields() = %v, want empty", got) + } +} + +func TestCustomColumnErrors(t *testing.T) { + for name, body := range map[string]string{ + "no source": "column.x = birch_pollen\ncolumns=hour,x\n", + "unknown source": "column.x = weather:birch_pollen\ncolumns=hour,x\n", + "empty field": "column.x = air:\ncolumns=hour,x\n", + "bad width": "column.x = air:f\nwidth.x = wide\n", + "bad decimals": "column.x = air:f\ndecimals.x = 9\n", + } { + t.Run(name, func(t *testing.T) { + if _, err := Load(write(t, body)); err == nil { + t.Fatalf("expected an error for %q", body) + } + }) + } +} + +// Attributes without a declaration are a typo, not a silent no-op. +func TestAttributesWithoutDeclarationAreRejected(t *testing.T) { + cfg, err := Load(write(t, "label.birch = brzoza\n")) + if err != nil { + t.Fatal(err) + } + if err := cfg.Validate(); err == nil { + t.Fatal("label.birch without column.birch must be an error") + } +} + +// Shadowing a built-in would make which column you get depend on lookup order. +func TestCustomColumnCannotShadowABuiltIn(t *testing.T) { + cfg, err := Load(write(t, "column.temp = air:birch_pollen\n")) + if err != nil { + t.Fatal(err) + } + err = cfg.Validate() + if err == nil || !strings.Contains(err.Error(), "built-in") { + t.Fatalf("expected a built-in clash error, got %v", err) + } +} + +// An undeclared column name should say how to declare it. +func TestUnknownColumnSuggestsDeclaringIt(t *testing.T) { + cfg := Default() + cfg.Columns = []string{"hour", "birch"} + err := cfg.Validate() + if err == nil || !strings.Contains(err.Error(), "column.birch") { + t.Fatalf("error should show how to declare it, got %v", err) + } +} + +func TestPollenExplicitTracksWhoChose(t *testing.T) { + cases := map[string]bool{ + "pollen=grass,birch\n": true, + "pollen=all\n": false, + "pollen=none\n": false, + } + for body, want := range cases { + cfg, err := Load(write(t, body)) + if err != nil { + t.Fatal(err) + } + if cfg.PollenExplicit != want { + t.Errorf("%q gave PollenExplicit=%v, want %v", body, cfg.PollenExplicit, want) + } + } + if Default().PollenExplicit { + t.Error("the default is not an explicit choice") + } +} |
