package notify import ( "encoding/json" "strings" "testing" ) // R-659 (v0.268.0) — app_hold_no_whole_copy: severity critical (the hub's vocabulary), the operator // message only (no household sentence — the hub bars the type from customers too), and the details // carry what support needs: app, from, to, at, copies_seen (`[]`, never null, when none were seen). func TestR659_NoWholeCopyEvent(t *testing.T) { n := &Notifier{} var et, sev, msg, cust string var det []byte n.pushFn = func(eventType, severity, message, customer string, details interface{}) { et, sev, msg, cust = eventType, severity, message, customer det, _ = json.Marshal(details) } n.NotifyAppHoldNoWholeCopy(AppHoldNoWholeCopyDetails{App: "nextcloud", StackName: "nextcloud", From: map[string]string{"nextcloud": "nextcloud:34.0.1"}, To: map[string]string{"nextcloud": "nextcloud:34.0.4"}, At: "2026-09-23T21:42:39Z", UndoState: "untouched"}) if et != "app_hold_no_whole_copy" || sev != "critical" || cust != "" { t.Fatalf("type=%q severity=%q customer=%q", et, sev, cust) } if !strings.Contains(msg, "nextcloud") || !strings.Contains(msg, "Support must act") { t.Fatalf("message = %q", msg) } for _, want := range []string{`"app":"nextcloud"`, `"stack_name":"nextcloud"`, `"copies_seen":[]`, `"at":"2026-09-23T21:42:39Z"`, `"from":{`, `"to":{`} { if !strings.Contains(string(det), want) { t.Fatalf("details %s lack %s", det, want) } } }