- internal/hub: project side of the frozen ask-contract. GET /capabilities, read-only POST /ask answerer (no LLM, <3s), and the outbound POST /notify client. - internal/apprise: daily-summary delivery through the house Apprise API. - internal/summary: deterministic plain-text daily summary builder. - internal/store: CountByCategory, MessagesByCategory, and summary CRUD. - internal/server: /capabilities and /ask (bearer-token protected), plus the Reports screen (/reports, build, send, delete). - main.go: -summary, -summary-send, and -notify CLI entry points for n8n. Co-Authored-By: Paperclip <noreply@paperclip.ing>
92 lines
2.6 KiB
Go
92 lines
2.6 KiB
Go
package apprise
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
type captured struct {
|
|
path string
|
|
auth string
|
|
body notifyBody
|
|
}
|
|
|
|
func TestSendWithKey(t *testing.T) {
|
|
var got captured
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
got.path = r.URL.Path
|
|
got.auth = r.Header.Get("Authorization")
|
|
_ = json.NewDecoder(r.Body).Decode(&got.body)
|
|
w.WriteHeader(http.StatusOK)
|
|
}))
|
|
defer srv.Close()
|
|
|
|
c := New(srv.URL, "email-summary", nil, "apprise-token", time.Second)
|
|
if err := c.Send(context.Background(), "Subject", "Body text"); err != nil {
|
|
t.Fatalf("Send() error = %v", err)
|
|
}
|
|
if got.path != "/notify/email-summary" {
|
|
t.Errorf("path = %q, want /notify/email-summary", got.path)
|
|
}
|
|
if got.auth != "Bearer apprise-token" {
|
|
t.Errorf("auth = %q", got.auth)
|
|
}
|
|
if got.body.Title != "Subject" || got.body.Body != "Body text" {
|
|
t.Errorf("body = %+v", got.body)
|
|
}
|
|
if got.body.Type != "info" {
|
|
t.Errorf("type = %q, want info", got.body.Type)
|
|
}
|
|
if len(got.body.URLs) != 0 {
|
|
t.Errorf("urls = %v, want none in key mode", got.body.URLs)
|
|
}
|
|
}
|
|
|
|
func TestSendStatelessURLs(t *testing.T) {
|
|
var got captured
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
got.path = r.URL.Path
|
|
_ = json.NewDecoder(r.Body).Decode(&got.body)
|
|
w.WriteHeader(http.StatusOK)
|
|
}))
|
|
defer srv.Close()
|
|
|
|
c := New(srv.URL, "", []string{"mailto://user:pass@example.com"}, "", time.Second)
|
|
if err := c.Send(context.Background(), "T", "B"); err != nil {
|
|
t.Fatalf("Send() error = %v", err)
|
|
}
|
|
if got.path != "/notify" {
|
|
t.Errorf("path = %q, want /notify", got.path)
|
|
}
|
|
if len(got.body.URLs) != 1 || got.body.URLs[0] != "mailto://user:pass@example.com" {
|
|
t.Errorf("urls = %v", got.body.URLs)
|
|
}
|
|
}
|
|
|
|
func TestSendErrorStatus(t *testing.T) {
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
http.Error(w, "bad", http.StatusUnauthorized)
|
|
}))
|
|
defer srv.Close()
|
|
c := New(srv.URL, "key", nil, "", time.Second)
|
|
if err := c.Send(context.Background(), "T", "B"); err == nil {
|
|
t.Fatal("expected an error for a 401 reply")
|
|
}
|
|
}
|
|
|
|
func TestConfigured(t *testing.T) {
|
|
if New("http://x", "", nil, "", time.Second).Configured() {
|
|
t.Error("keyless and urlless client reports configured")
|
|
}
|
|
if New("http://x", "k", nil, "", time.Second).Configured() != true {
|
|
t.Error("key client should report configured")
|
|
}
|
|
if New("http://x", "", []string{"mailto://a@b"}, "", time.Second).Configured() != true {
|
|
t.Error("url client should report configured")
|
|
}
|
|
}
|