package api import "testing" // What a car's page shows — which tabs, which rows of the Information tab, and // the order those rows are laid out in — is stored on the car as key lists, so // the validation has to keep them to keys the page actually renders. // Information itself stays out of the hideable tabs: a car with no tabs left // would be a dead end. func TestNormalizeHiddenTabs(t *testing.T) { got, err := normalizeKeys([]string{" fuel ", "parts", "fuel", ""}, hideableCarTabs, "tab") if err != nil { t.Fatalf("normalizeKeys: %v", err) } want := []string{"fuel", "parts"} // trimmed, blanks dropped, deduped assertKeys(t, got, want) // Clearing the list is how a car goes back to showing everything. if empty, err := normalizeKeys(nil, hideableCarTabs, "tab"); err != nil || len(empty) != 0 { t.Errorf("normalizeKeys(nil) = %v, %v; want empty and no error", empty, err) } // Information is the car itself; hiding it would leave a page with no tabs. if _, err := normalizeKeys([]string{"info"}, hideableCarTabs, "tab"); err == nil { t.Error("normalizeKeys allowed hiding the info tab, want an error") } // A key from a stale or wrong client is an error, not something to drop // quietly while the tab stays visible. if _, err := normalizeKeys([]string{"fuel", "nonsense"}, hideableCarTabs, "tab"); err == nil { t.Error("normalizeKeys accepted an unknown tab, want an error") } // The hideable set is the contract the web app's HIDEABLE_TABS mirrors: // every tab the car page renders beside Information. for _, key := range []string{"provider", "services", "technical", "maintenance", "fuel", "documents", "parts", "reminders"} { if !hideableCarTabs[key] { t.Errorf("tab %q should be hideable", key) } } if len(hideableCarTabs) != 8 { t.Errorf("hideableCarTabs has %d entries, want the 8 tabs beside Information", len(hideableCarTabs)) } } func TestNormalizeHiddenFields(t *testing.T) { got, err := normalizeKeys([]string{"vin", " differentialOil ", "vin"}, hideableCarFields, "field") if err != nil { t.Fatalf("normalizeKeys: %v", err) } assertKeys(t, got, []string{"vin", "differentialOil"}) if _, err := normalizeKeys([]string{"oilSpec", "nonsense"}, hideableCarFields, "field"); err == nil { t.Error("normalizeKeys accepted an unknown field, want an error") } // A tab key is not a field key — the two sets are validated separately. if _, err := normalizeKeys([]string{"fuel"}, hideableCarFields, "field"); err == nil { t.Error("normalizeKeys accepted a tab key as a field, want an error") } // Every Information row the web app renders must be hideable; unlike the // tabs there is no row the page has to keep. for _, key := range []string{ "oilSpec", "transmissionOil", "differentialOil", "brakeFluid", "coolant", "odometer", "serviceInterval", "nextDue", "registrationPlate", "registrationCountry", "vin", "fuelType", "buildDate", "firstRegistration", } { if !hideableCarFields[key] { t.Errorf("field %q should be hideable", key) } } if len(hideableCarFields) != 14 { t.Errorf("hideableCarFields has %d entries, want the 14 Information rows", len(hideableCarFields)) } } // The arrangement of the Information rows shares the field key set — every row // can be moved — but not the meaning: here the order of the list is the point, // so it has to survive validation exactly as it was sent. func TestNormalizeFieldOrder(t *testing.T) { got, err := normalizeKeys([]string{"vin", "odometer", "oilSpec"}, hideableCarFields, "field") if err != nil { t.Fatalf("normalizeKeys: %v", err) } assertKeys(t, got, []string{"vin", "odometer", "oilSpec"}) // A key repeated by a client that lost track keeps its first position; a // second entry for the same row would put it in two places at once. got, err = normalizeKeys([]string{"vin", "odometer", "vin"}, hideableCarFields, "field") if err != nil { t.Fatalf("normalizeKeys: %v", err) } assertKeys(t, got, []string{"vin", "odometer"}) // A partial arrangement is fine — the rows it leaves out follow the arranged // ones — but an invented row is still an error. if _, err := normalizeKeys([]string{"vin", "nonsense"}, hideableCarFields, "field"); err == nil { t.Error("normalizeKeys accepted an unknown field in an arrangement, want an error") } } func assertKeys(t *testing.T, got, want []string) { t.Helper() if len(got) != len(want) { t.Fatalf("keys = %v, want %v", got, want) } for i := range got { if got[i] != want[i] { t.Fatalf("keys = %v, want %v", got, want) } } }