35c6ff5a71
Persist reminder presentations and retry state, atomically complete collapsed deliveries, fall back across away reaches, and block permanent failures visibly (V-715, V-678). Fail closed when enabled integrations lack credentials and keep remote arms explicitly dark (V-691). Give mavweb one sanitized, request-correlated error contract (V-689). Owner explicitly requested direct commits to master.
60 lines
1.9 KiB
Go
60 lines
1.9 KiB
Go
package main
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/kami/maven/internal/ipc"
|
|
)
|
|
|
|
// The page showed the storage envelope and the UTC instant (Vikunja #469).
|
|
func TestReminderRowsUnwrapAndLocalise(t *testing.T) {
|
|
fire := time.Date(2026, 8, 4, 18, 30, 0, 0, time.UTC)
|
|
rows := reminderRows([]ipc.Reminder{{
|
|
CreatedTs: fire.Add(-time.Hour),
|
|
FireTs: fire,
|
|
Status: "pending",
|
|
Payload: `{"text":"выпить таблетки"}`,
|
|
}})
|
|
if len(rows) != 1 {
|
|
t.Fatalf("rows = %d, want 1", len(rows))
|
|
}
|
|
if rows[0].Text != "выпить таблетки" {
|
|
t.Errorf("Text = %q, want the words without the envelope", rows[0].Text)
|
|
}
|
|
if want := fire.Local().Format("02 Jan 15:04"); rows[0].Fires != want {
|
|
t.Errorf("Fires = %q, want %q", rows[0].Fires, want)
|
|
}
|
|
if strings.Contains(rows[0].Text, "{") {
|
|
t.Errorf("Text still carries JSON: %q", rows[0].Text)
|
|
}
|
|
}
|
|
|
|
func TestReminderRowsExposeBlockedDelivery(t *testing.T) {
|
|
blocked := time.Date(2026, 8, 13, 8, 0, 0, 0, time.UTC)
|
|
rows := reminderRows([]ipc.Reminder{{
|
|
Status: "pending",
|
|
Payload: `{"text":"позвонить врачу"}`,
|
|
DeliveryBlockedTs: blocked,
|
|
DeliveryBlockedError: "ntfy credentials rejected",
|
|
}})
|
|
if len(rows) != 1 || rows[0].Status != "blocked" || rows[0].Detail != "ntfy credentials rejected" {
|
|
t.Fatalf("blocked reminder is not visible: %+v", rows)
|
|
}
|
|
}
|
|
|
|
// A payload that is not the envelope is his own words, so it is shown as it is.
|
|
func TestReminderTextKeepsPlainPayload(t *testing.T) {
|
|
for _, tc := range []struct{ in, want string }{
|
|
{`{"text":"позвонить маме"}`, "позвонить маме"},
|
|
{" полить цветы ", "полить цветы"},
|
|
{`{"body":"nope"}`, `{"body":"nope"}`},
|
|
{"", ""},
|
|
} {
|
|
if got := reminderText(tc.in); got != tc.want {
|
|
t.Errorf("reminderText(%q) = %q, want %q", tc.in, got, tc.want)
|
|
}
|
|
}
|
|
}
|