You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
93 lines
3.3 KiB
93 lines
3.3 KiB
package web
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"reflect"
|
|
"strings"
|
|
"testing"
|
|
|
|
"mqtt_washingmachine/internal/status"
|
|
)
|
|
|
|
func TestStatusAPI(t *testing.T) {
|
|
for _, tt := range []struct {
|
|
name, state, message string
|
|
readings []status.Sample
|
|
}{
|
|
{"startup", "waiting", "Waiting for data...", []status.Sample{}},
|
|
{"waiting", "waiting", "Waiting for data...", []status.Sample{{Power: 47.7, Valid: true}}},
|
|
{"incomplete", "incomplete", "Incomplete data", []status.Sample{{Power: 47.7, Valid: true}, {}, {Valid: true}}},
|
|
{"running", "running", "Laundry not yet done", []status.Sample{{Valid: true}, {Power: 3, Valid: true}, {Valid: true}}},
|
|
{"done", "done", "Laundry done", []status.Sample{{Power: 2.99, Valid: true}, {Valid: true}, {Valid: true}}},
|
|
} {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
handler := NewHandler(func() status.Result { return status.Evaluate(tt.readings) })
|
|
response := httptest.NewRecorder()
|
|
handler.ServeHTTP(response, httptest.NewRequest(http.MethodGet, "/api/status", nil))
|
|
if response.Code != http.StatusOK {
|
|
t.Fatalf("status = %d", response.Code)
|
|
}
|
|
if got := response.Header().Get("Content-Type"); got != "application/json" {
|
|
t.Errorf("content type = %q", got)
|
|
}
|
|
if got := response.Header().Get("Cache-Control"); got != "no-store" {
|
|
t.Errorf("cache control = %q", got)
|
|
}
|
|
var got status.Result
|
|
if err := json.Unmarshal(response.Body.Bytes(), &got); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
want := status.Result{State: tt.state, Message: tt.message, Readings: tt.readings}
|
|
if !reflect.DeepEqual(got, want) {
|
|
t.Fatalf("body = %+v; want %+v", got, want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestPageAndRouting(t *testing.T) {
|
|
handler := NewHandler(func() status.Result { return status.Evaluate(nil) })
|
|
page := httptest.NewRecorder()
|
|
handler.ServeHTTP(page, httptest.NewRequest(http.MethodGet, "/", nil))
|
|
if page.Code != http.StatusOK || !strings.HasPrefix(page.Header().Get("Content-Type"), "text/html") {
|
|
t.Fatalf("page response: %+v", page.Result())
|
|
}
|
|
for _, text := range []string{`name="viewport"`, "Waiting for data...", "/api/status", "60000", "toFixed(2)", "--", "clamp("} {
|
|
if !strings.Contains(page.Body.String(), text) {
|
|
t.Errorf("page missing %q", text)
|
|
}
|
|
}
|
|
for _, tt := range []struct {
|
|
method, path string
|
|
code int
|
|
}{
|
|
{http.MethodGet, "/missing", http.StatusNotFound},
|
|
{http.MethodPost, "/api/status", http.StatusMethodNotAllowed},
|
|
{http.MethodPost, "/", http.StatusMethodNotAllowed},
|
|
} {
|
|
response := httptest.NewRecorder()
|
|
handler.ServeHTTP(response, httptest.NewRequest(tt.method, tt.path, nil))
|
|
if response.Code != tt.code {
|
|
t.Errorf("%s %s = %d; want %d", tt.method, tt.path, response.Code, tt.code)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestStatusAPIReadsCurrentSnapshot(t *testing.T) {
|
|
var window status.Window
|
|
handler := NewHandler(func() status.Result { return status.Evaluate(window.Readings()) })
|
|
for range 3 {
|
|
window.Add(status.Sample{Valid: true})
|
|
response := httptest.NewRecorder()
|
|
handler.ServeHTTP(response, httptest.NewRequest(http.MethodGet, "/api/status", nil))
|
|
var got status.Result
|
|
if err := json.Unmarshal(response.Body.Bytes(), &got); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !reflect.DeepEqual(got.Readings, window.Readings()) {
|
|
t.Fatal("handler returned stale readings")
|
|
}
|
|
}
|
|
}
|
|
|