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

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")
}
}
}