72 lines
1.8 KiB
Go
72 lines
1.8 KiB
Go
package store
|
|
|
|
import (
|
|
"context"
|
|
"path/filepath"
|
|
"testing"
|
|
)
|
|
|
|
func TestMigration0013AlertsLastSeen(t *testing.T) {
|
|
t.Parallel()
|
|
dir := t.TempDir()
|
|
st, err := Open(context.Background(), filepath.Join(dir, "rm.db"))
|
|
if err != nil {
|
|
t.Fatalf("open: %v", err)
|
|
}
|
|
defer st.Close()
|
|
|
|
// Column must exist after migration. Best signal: PRAGMA table_info.
|
|
rows, err := st.DB().Query(`SELECT name FROM pragma_table_info('alerts')`)
|
|
if err != nil {
|
|
t.Fatalf("pragma: %v", err)
|
|
}
|
|
defer rows.Close()
|
|
cols := map[string]bool{}
|
|
for rows.Next() {
|
|
var n string
|
|
if err := rows.Scan(&n); err != nil {
|
|
t.Fatalf("scan: %v", err)
|
|
}
|
|
cols[n] = true
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
t.Fatalf("rows iter: %v", err)
|
|
}
|
|
if !cols["last_seen_at"] {
|
|
t.Fatalf("alerts.last_seen_at not present after migration; cols=%v", cols)
|
|
}
|
|
}
|
|
|
|
func TestMigration0014NotificationsTables(t *testing.T) {
|
|
t.Parallel()
|
|
dir := t.TempDir()
|
|
st, err := Open(context.Background(), filepath.Join(dir, "rm.db"))
|
|
if err != nil {
|
|
t.Fatalf("open: %v", err)
|
|
}
|
|
defer st.Close()
|
|
|
|
for _, want := range []string{"notification_channels", "notification_log"} {
|
|
var n int
|
|
if err := st.DB().QueryRow(
|
|
`SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name=?`, want,
|
|
).Scan(&n); err != nil {
|
|
t.Fatalf("scan: %v", err)
|
|
}
|
|
if n != 1 {
|
|
t.Errorf("table %q missing after migration", want)
|
|
}
|
|
}
|
|
|
|
// Sanity: kind CHECK accepts all three v1 kinds.
|
|
for _, k := range []string{"webhook", "ntfy", "smtp"} {
|
|
_, err := st.DB().Exec(
|
|
`INSERT INTO notification_channels (id, kind, name, config, created_at, updated_at)
|
|
VALUES (?, ?, ?, x'00', '2026-01-01T00:00:00Z', '2026-01-01T00:00:00Z')`,
|
|
"test-"+k, k, "test-"+k)
|
|
if err != nil {
|
|
t.Errorf("insert %q rejected by CHECK: %v", k, err)
|
|
}
|
|
}
|
|
}
|