Skip to content
quarry Artifact [e0597232e5]
Login

Artifact [e0597232e5]

Artifact e0597232e5993d65c09d1f72513feecdf94f4ae57647194085c4915aec0a9e8a:


package notify

import (
	"context"
	"encoding/json"
	"net/http"
	"net/http/httptest"
	"testing"
)

// notify's /v1 routes sit behind an API-key middleware, so a client
// without the header is answered 401 on every call. quarry shipped
// exactly that for triggers until this was noticed — silent, because a
// trigger failure is logged rather than raised.
func TestRequestsCarryTheAPIKey(t *testing.T) {
	seen := make(chan string, 2)
	srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		seen <- r.Header.Get("Authorization")
		if r.URL.Path == "/v1/messages" {
			json.NewEncoder(w).Encode([]Message{})
			return
		}
		w.WriteHeader(http.StatusOK)
	}))
	defer srv.Close()

	c := New(srv.URL, "key-123")
	if err := c.Trigger(context.Background(), "quarry-activity",
		Recipient{SubscriberID: "dan"}, map[string]any{}, "txn"); err != nil {
		t.Fatal(err)
	}
	if got := <-seen; got != "ApiKey key-123" {
		t.Errorf("trigger Authorization = %q", got)
	}
	if _, err := c.Inbox(context.Background(), "dan"); err != nil {
		t.Fatal(err)
	}
	if got := <-seen; got != "ApiKey key-123" {
		t.Errorf("inbox Authorization = %q", got)
	}
}

// The wire field names are notify's Go field names: its domain.Message
// carries db tags but no json tags, so the encoder falls back to the
// identifiers. Decoding lowercase would silently yield empty subjects.
func TestInboxDecodesNotifysWireNames(t *testing.T) {
	srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if got := r.URL.Query().Get("channel"); got != "in_app" {
			t.Errorf("channel = %q, want in_app", got)
		}
		if got := r.URL.Query().Get("subscriberId"); got != "dan" {
			t.Errorf("subscriberId = %q", got)
		}
		w.Write([]byte(`[{"ID":"m1","Subject":"you were mentioned",
			"Content":"in ticket abc","Read":false,"CreatedAt":"2026-08-16T00:00:00Z"}]`))
	}))
	defer srv.Close()

	msgs, err := New(srv.URL, "k").Inbox(context.Background(), "dan")
	if err != nil {
		t.Fatal(err)
	}
	if len(msgs) != 1 {
		t.Fatalf("got %d messages", len(msgs))
	}
	if msgs[0].Subject != "you were mentioned" || msgs[0].ID != "m1" || msgs[0].Read {
		t.Fatalf("decoded %+v", msgs[0])
	}
}

// A disabled client (no --notify) answers empty without a call, so the
// inbox is simply absent rather than an error surface.
func TestDisabledClientIsQuiet(t *testing.T) {
	msgs, err := New("", "").Inbox(context.Background(), "dan")
	if err != nil || msgs != nil {
		t.Fatalf("disabled client returned (%v, %v)", msgs, err)
	}
}