fix: refresh dashboard update runs live
Container-Image veröffentlichen / container (push) Multi-Arch-Image veröffentlicht und verifiziert
Container-Image veröffentlichen / container (push) Multi-Arch-Image veröffentlicht und verifiziert
This commit is contained in:
1 parent
bb60c06c0e
commit
fc59092030
11 files changed
+241
-29
No files matched your search
@@ -4,6 +4,8 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
@@ -18,6 +20,7 @@ import (
|
||||
"github.com/root-kdw12/hetzner-api-dyndns-records-webinterface/internal/config"
|
||||
"github.com/root-kdw12/hetzner-api-dyndns-records-webinterface/internal/model"
|
||||
"github.com/root-kdw12/hetzner-api-dyndns-records-webinterface/internal/pihole"
|
||||
"github.com/root-kdw12/hetzner-api-dyndns-records-webinterface/internal/scheduler"
|
||||
"github.com/root-kdw12/hetzner-api-dyndns-records-webinterface/internal/secure"
|
||||
"github.com/root-kdw12/hetzner-api-dyndns-records-webinterface/internal/store"
|
||||
)
|
||||
@@ -232,6 +235,93 @@ func TestLoginErrorRendersAsToast(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestDashboardRendersLiveUpdateHooks(t *testing.T) {
|
||||
t.Parallel()
|
||||
templates, err := loadTemplates()
|
||||
if err != nil {
|
||||
t.Fatalf("load templates: %v", err)
|
||||
}
|
||||
var rendered bytes.Buffer
|
||||
data := viewData{
|
||||
Title: "Übersicht",
|
||||
Page: "dashboard",
|
||||
CSRF: "csrf-token",
|
||||
User: model.User{DisplayName: "Admin", Username: "admin"},
|
||||
IsAdmin: true,
|
||||
Dashboard: model.Dashboard{
|
||||
Settings: model.Settings{UpdaterEnabled: true, IPv6Enabled: true},
|
||||
SchedulerRunning: true,
|
||||
RecentRuns: []model.UpdateRun{{ID: 1, StartedAt: time.Now(), Status: "running"}},
|
||||
},
|
||||
}
|
||||
if err := templates["dashboard"].ExecuteTemplate(&rendered, "dashboard", data); err != nil {
|
||||
t.Fatalf("render dashboard: %v", err)
|
||||
}
|
||||
body := rendered.String()
|
||||
for _, expected := range []string{
|
||||
`data-run-now-button disabled`,
|
||||
`data-dashboard-ipv4`,
|
||||
`data-dashboard-ipv6`,
|
||||
`data-recent-runs aria-live="polite" aria-busy="true"`,
|
||||
`Aktualisierung läuft`,
|
||||
`features-24`,
|
||||
} {
|
||||
if !strings.Contains(body, expected) {
|
||||
t.Errorf("rendered dashboard is missing %q", expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSchedulerAPIIncludesRecentRunsOnlyForAdministrators(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx := context.Background()
|
||||
database, err := store.Open(ctx, filepath.Join(t.TempDir(), "app.db"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Cleanup(func() { _ = database.Close() })
|
||||
runID, err := database.CreateUpdateRun(ctx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := database.FinishUpdateRun(ctx, runID, "ok", "198.51.100.10", "", "1 Ziel aktualisiert"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
schedule := scheduler.New(database, nil, nil, nil, slog.Default())
|
||||
server := &Server{store: database, scheduler: schedule}
|
||||
|
||||
adminResponse := httptest.NewRecorder()
|
||||
adminRequest := httptest.NewRequest(http.MethodGet, "/api/v1/scheduler?runs=1", nil)
|
||||
server.schedulerAPI(adminResponse, adminRequest, &model.Session{Role: "admin"})
|
||||
if adminResponse.Code != http.StatusOK {
|
||||
t.Fatalf("unexpected admin response: status=%d body=%s", adminResponse.Code, adminResponse.Body.String())
|
||||
}
|
||||
if got := adminResponse.Header().Get("Cache-Control"); got != "no-store" {
|
||||
t.Fatalf("unexpected cache policy: %q", got)
|
||||
}
|
||||
var adminState schedulerResponse
|
||||
if err := json.NewDecoder(adminResponse.Body).Decode(&adminState); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if adminState.RecentRuns == nil || len(*adminState.RecentRuns) != 1 {
|
||||
t.Fatalf("administrator did not receive recent runs: %#v", adminState.RecentRuns)
|
||||
}
|
||||
if run := (*adminState.RecentRuns)[0]; run.ID != runID || run.Status != "ok" || run.Summary != "1 Ziel aktualisiert" {
|
||||
t.Fatalf("unexpected recent run: %#v", run)
|
||||
}
|
||||
|
||||
memberResponse := httptest.NewRecorder()
|
||||
memberRequest := httptest.NewRequest(http.MethodGet, "/api/v1/scheduler?runs=1", nil)
|
||||
server.schedulerAPI(memberResponse, memberRequest, &model.Session{Role: "member"})
|
||||
var memberState schedulerResponse
|
||||
if err := json.NewDecoder(memberResponse.Body).Decode(&memberState); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if memberState.RecentRuns != nil {
|
||||
t.Fatal("member received administrator-only update runs")
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoginLimiterPrunesExpiredClientsAndBoundsMemory(t *testing.T) {
|
||||
t.Parallel()
|
||||
limiter := newLoginLimiter()
|
||||
|
||||
Reference in new issue
Block a user