feat: add webhook thought ingestion
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"git.warky.dev/wdevs/amcs/internal/config"
|
||||
)
|
||||
|
||||
func TestParseWebhookThoughtRequestRequiresJSON(t *testing.T) {
|
||||
req := httptestRequest("text/plain", `{"content":"hello"}`)
|
||||
|
||||
_, err := parseWebhookThoughtRequest(req)
|
||||
if err == nil {
|
||||
t.Fatal("expected error for non-json content type")
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseWebhookThoughtRequestRequiresContent(t *testing.T) {
|
||||
req := httptestRequest("application/json", `{"source":"n8n"}`)
|
||||
|
||||
_, err := parseWebhookThoughtRequest(req)
|
||||
if err == nil || !strings.Contains(err.Error(), "content is required") {
|
||||
t.Fatalf("error = %v, want content required", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildWebhookMetadataUsesHeaderIdempotencyAndSanitizesMetadata(t *testing.T) {
|
||||
now := time.Date(2026, 7, 15, 4, 0, 0, 0, time.UTC)
|
||||
got := buildWebhookMetadata(webhookThoughtRequest{
|
||||
ExternalID: " ext-1 ",
|
||||
Metadata: map[string]any{
|
||||
"service": "n8n",
|
||||
"unsafe": struct{}{},
|
||||
"nested": map[string]any{"ok": true},
|
||||
},
|
||||
}, " key-1 ", now)
|
||||
|
||||
if got.IDempotencyKey != "key-1" {
|
||||
t.Fatalf("IDempotencyKey = %q, want key-1", got.IDempotencyKey)
|
||||
}
|
||||
if got.ExternalID != "ext-1" {
|
||||
t.Fatalf("ExternalID = %q, want ext-1", got.ExternalID)
|
||||
}
|
||||
if got.ReceivedAt != "2026-07-15T04:00:00Z" {
|
||||
t.Fatalf("ReceivedAt = %q", got.ReceivedAt)
|
||||
}
|
||||
if _, ok := got.SourceMetadata["unsafe"]; ok {
|
||||
t.Fatal("unsafe metadata value was not removed")
|
||||
}
|
||||
if got.SourceMetadata["service"] != "n8n" {
|
||||
t.Fatalf("service metadata = %#v", got.SourceMetadata["service"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestNormalizeWebhookThoughtMetadata(t *testing.T) {
|
||||
webhookMeta := buildWebhookMetadata(webhookThoughtRequest{IDempotencyKey: "abc"}, "", time.Date(2026, 7, 15, 4, 0, 0, 0, time.UTC))
|
||||
got := normalizeWebhookThoughtMetadata(webhookThoughtRequest{
|
||||
Source: "github",
|
||||
Type: "task",
|
||||
Topics: []string{"ci", "ci", ""},
|
||||
People: []string{" Sam "},
|
||||
}, webhookMeta, config.CaptureConfig{})
|
||||
|
||||
if got.Source != "github" {
|
||||
t.Fatalf("Source = %q, want github", got.Source)
|
||||
}
|
||||
if got.Type != "task" {
|
||||
t.Fatalf("Type = %q, want task", got.Type)
|
||||
}
|
||||
if len(got.Topics) != 1 || got.Topics[0] != "ci" {
|
||||
t.Fatalf("Topics = %#v, want [ci]", got.Topics)
|
||||
}
|
||||
if got.Webhook == nil || got.Webhook.IDempotencyKey != "abc" {
|
||||
t.Fatalf("Webhook = %#v, want idempotency key abc", got.Webhook)
|
||||
}
|
||||
}
|
||||
|
||||
func httptestRequest(contentType, body string) *http.Request {
|
||||
req := httptest.NewRequest(http.MethodPost, "/webhooks/thoughts", strings.NewReader(body))
|
||||
req.Header.Set("Content-Type", contentType)
|
||||
return req
|
||||
}
|
||||
Reference in New Issue
Block a user