80 lines
3.1 KiB
Go
80 lines
3.1 KiB
Go
package web
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"io"
|
|
"log"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"gitea.dooplex.hu/admin/felhom-controller/internal/agentapi"
|
|
)
|
|
|
|
// D65 = A: after the operator rebooted the box from the hub, the household's dashboard says so — one neutral line,
|
|
// for one day, then gone.
|
|
|
|
// The real dashboard, through ServeHTTP: the line is there after an operator reboot, in Hungarian, with the Budapest
|
|
// time; it is gone a day later. RED-PROOF: drop the data["OperatorRebootNotice"] line from dashboardHandler → FAILS;
|
|
// drop the 24-hour check → the day-later page still shows it → FAILS.
|
|
func TestOperatorRebootNotice_OnTheDashboardForADay(t *testing.T) {
|
|
s := newDashboardServer(t, time.Time{})
|
|
if body := getPage(t, s, "/dashboard").Body.String(); strings.Contains(body, "data-operator-reboot") {
|
|
t.Fatal("no reboot yet, but the dashboard shows the line")
|
|
}
|
|
at := time.Now().Add(-2 * time.Hour)
|
|
s.SetOperatorReboot(at)
|
|
body := getPage(t, s, "/dashboard").Body.String()
|
|
want := "A Felhom ügyfélszolgálata " + at.In(budapestLocation()).Format("15:04") + "-kor újraindította a dobozt."
|
|
if !strings.Contains(body, want) {
|
|
t.Fatalf("the dashboard lacks %q", want)
|
|
}
|
|
s.SetOperatorReboot(time.Now().Add(-25 * time.Hour))
|
|
if body := getPage(t, s, "/dashboard").Body.String(); strings.Contains(body, "data-operator-reboot") {
|
|
t.Fatal("a day later the line must be gone")
|
|
}
|
|
}
|
|
|
|
// English: the reader's language.
|
|
func TestOperatorRebootNotice_English(t *testing.T) {
|
|
s := newDashboardServer(t, time.Time{})
|
|
at := time.Date(2026, 10, 30, 9, 41, 0, 0, time.UTC)
|
|
s.SetOperatorReboot(at)
|
|
got := s.operatorRebootNotice("en", at.Add(time.Hour))
|
|
if got != "Felhom support restarted your box at "+at.In(budapestLocation()).Format("15:04")+"." {
|
|
t.Fatalf("en: %q", got)
|
|
}
|
|
}
|
|
|
|
// The start-up ask: it retries while the agent does not answer, keeps the time it gets, and stops at once on a 404
|
|
// (an agent older than the route cannot reboot from the hub). RED-PROOF: drop SetOperatorReboot from the success
|
|
// branch → FAILS; return on the first error → the retried answer is lost → FAILS.
|
|
func TestWatchOperatorReboot_RetriesAndKeepsTheTime(t *testing.T) {
|
|
s := &Server{logger: log.New(io.Discard, "", 0), opRebootRetry: time.Millisecond}
|
|
at := time.Date(2026, 10, 30, 9, 41, 0, 0, time.UTC)
|
|
calls := 0
|
|
s.opRebootFetch = func(context.Context) (time.Time, error) {
|
|
calls++
|
|
if calls < 3 {
|
|
return time.Time{}, errors.New("agentapi: GET /guest/operator-reboot: connection refused")
|
|
}
|
|
return at, nil
|
|
}
|
|
s.WatchOperatorReboot(context.Background())
|
|
if calls != 3 || !s.opRebootAt.Equal(at) {
|
|
t.Fatalf("calls=%d at=%v, want 3 and %v", calls, s.opRebootAt, at)
|
|
}
|
|
|
|
s2 := &Server{logger: log.New(io.Discard, "", 0), opRebootRetry: time.Millisecond}
|
|
calls = 0
|
|
s2.opRebootFetch = func(context.Context) (time.Time, error) {
|
|
calls++
|
|
return time.Time{}, &agentapi.StatusError{Path: "/guest/operator-reboot", Code: 404}
|
|
}
|
|
s2.WatchOperatorReboot(context.Background())
|
|
if calls != 1 || !s2.opRebootAt.IsZero() {
|
|
t.Fatalf("a 404 must end the ask at once: calls=%d at=%v", calls, s2.opRebootAt)
|
|
}
|
|
}
|