aboutsummaryrefslogtreecommitdiff
path: root/internal/config/config_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/config/config_test.go')
-rw-r--r--internal/config/config_test.go123
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")
+ }
+}