Add server-side rendered setup UI accessible via `heatwave web`. The dashboard is now re-rendered per request and includes a nav bar linking to the new /setup page. Setup provides full CRUD for profiles, rooms, devices, occupants, AC units (with room assignment), scenario toggles, and forecast fetching — all via POST/redirect/GET forms. - Add ShowNav field to DashboardData for conditional nav bar - Extract fetchForecastForProfile() for reuse by web handler - Create setup.html.tmpl with Tailwind-styled entity sections - Create web_handlers.go with 15 route handlers and flash cookies - Switch web.go from pre-rendered to per-request dashboard rendering - Graceful dashboard fallback when no forecast data exists
42 lines
978 B
Go
42 lines
978 B
Go
package action
|
|
|
|
import "testing"
|
|
|
|
func TestLoadDefaultActions(t *testing.T) {
|
|
actions, err := LoadDefaultActions()
|
|
if err != nil {
|
|
t.Fatalf("LoadDefaultActions: %v", err)
|
|
}
|
|
if len(actions) != 10 {
|
|
t.Errorf("len = %d, want 10", len(actions))
|
|
}
|
|
for _, a := range actions {
|
|
if a.ID == "" {
|
|
t.Error("action has empty ID")
|
|
}
|
|
if a.Name == "" {
|
|
t.Errorf("action %s has empty Name", a.ID)
|
|
}
|
|
if a.Category == "" {
|
|
t.Errorf("action %s has empty Category", a.ID)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestLoadDefaultActions_Categories(t *testing.T) {
|
|
actions, _ := LoadDefaultActions()
|
|
categories := make(map[Category]int)
|
|
for _, a := range actions {
|
|
categories[a.Category]++
|
|
}
|
|
if categories[Shading] != 2 {
|
|
t.Errorf("Shading actions = %d, want 2", categories[Shading])
|
|
}
|
|
if categories[Ventilation] != 2 {
|
|
t.Errorf("Ventilation actions = %d, want 2", categories[Ventilation])
|
|
}
|
|
if categories[Care] != 1 {
|
|
t.Errorf("Care actions = %d, want 1", categories[Care])
|
|
}
|
|
}
|