fe9266f53f
New report.Trigger (buffered-1 chan + worker; quiet 2s, min spacing 15s, trailing-edge coalescing) generalizes the v0.70.0 geo out-of-band push. One canonical fire closure in main.go; wired: geo save/sync + app deploy/remove/delete (api reportPushNow), escrow recovery-code claim, notification-prefs save, app-email toggle, offsite config + per-app toggle, customer claim (web SetReportTrigger seam, nil-safe, fired only after a successful local commit). 15-min hub-report cycle untouched as the reconciliation backbone; hub.enabled=false stays a strict no-op. Tests: trigger engine (2 red-proofs), seam fires-after-commit-only, nil-seam no-ops.
57 lines
2.0 KiB
Go
57 lines
2.0 KiB
Go
package web
|
|
|
|
import (
|
|
"io"
|
|
"log"
|
|
"net/http/httptest"
|
|
"net/url"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
|
|
"gitea.dooplex.hu/admin/felhom-controller/internal/settings"
|
|
)
|
|
|
|
// Group D (Scenario D): with the seam unset (hub reporting off / nil trigger), the helper
|
|
// is a strict nil-safe no-op — a handler calling it must never panic.
|
|
func TestReportTriggerNow_NilSeamIsNoOp(t *testing.T) {
|
|
s := &Server{}
|
|
s.reportTriggerNow() // must not panic with reportTriggerFn == nil
|
|
}
|
|
|
|
// The wired seam fires on a SUCCESSFUL local commit and does NOT fire on the error path
|
|
// (§Part 3: after the successful local commit — never before, never on error). Exercised
|
|
// through a real handler (offbox per-app toggle) so deleting the call site fails this test.
|
|
func TestReportTriggerNow_FiresAfterSuccessfulCommitOnly(t *testing.T) {
|
|
tmp := t.TempDir()
|
|
lg := log.New(io.Discard, "", 0)
|
|
sett, err := settings.Load(filepath.Join(tmp, "settings.json"), lg)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
fired := 0
|
|
s := &Server{settings: sett, logger: lg}
|
|
s.SetReportTrigger(func() { fired++ })
|
|
|
|
// Error path: missing app param → refused, trigger must NOT fire.
|
|
w := httptest.NewRecorder()
|
|
req := httptest.NewRequest("POST", "/backup/offbox/toggle", strings.NewReader(url.Values{"enabled": {"on"}}.Encode()))
|
|
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
|
s.offboxToggleHandler(w, req)
|
|
if fired != 0 {
|
|
t.Fatalf("trigger fired %d time(s) on the refused save, want 0 (never on the error path)", fired)
|
|
}
|
|
|
|
// Success path: the setting commits → the trigger fires exactly once.
|
|
w2 := httptest.NewRecorder()
|
|
req2 := httptest.NewRequest("POST", "/backup/offbox/toggle", strings.NewReader(url.Values{"app": {"immich"}, "enabled": {"on"}}.Encode()))
|
|
req2.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
|
s.offboxToggleHandler(w2, req2)
|
|
if !sett.IsAppOffbox("immich") {
|
|
t.Fatal("toggle did not commit — precondition for the trigger assertion")
|
|
}
|
|
if fired != 1 {
|
|
t.Fatalf("trigger fired %d time(s) after the successful save, want exactly 1", fired)
|
|
}
|
|
}
|