package config import ( "strings" "testing" ) func TestParse_FullValid(t *testing.T) { body := []byte(` agent: foreman inbox_dir: /tmp/inbox sources: webhook: listen: 127.0.0.1:18790 routes: /forgejo/push: recipient: bob type: INFO payload_template: "push to {{ .repo }}" /alert: recipient: bob type: NEEDS-RESPONSE priority: urgent payload_template: "alert" drop_folder: path: /tmp/incoming poll_fallback_seconds: 60 `) c, err := parse(body) if err != nil { t.Fatal(err) } if c.Agent != "foreman" { t.Errorf("agent = %q", c.Agent) } if c.InboxDir != "/tmp/inbox" { t.Errorf("inbox = %q", c.InboxDir) } if c.Sources.Webhook == nil || len(c.Sources.Webhook.Routes) != 2 { t.Errorf("webhook routes: %+v", c.Sources.Webhook) } if c.Sources.DropFolder == nil || c.Sources.DropFolder.Path != "/tmp/incoming" { t.Errorf("dropfolder: %+v", c.Sources.DropFolder) } } func TestParse_AppliesDefaults(t *testing.T) { body := []byte(` agent: foreman sources: drop_folder: path: /tmp/x `) c, err := parse(body) if err != nil { t.Fatal(err) } if c.InboxDir == "" { t.Error("inbox_dir default not applied") } if c.Sources.DropFolder.PollFallbackSeconds != DefaultPollFallbackSeconds { t.Errorf("poll default = %d", c.Sources.DropFolder.PollFallbackSeconds) } } func TestParse_HomeExpansion(t *testing.T) { body := []byte(` agent: foreman sources: drop_folder: path: ~/foo/bar `) c, err := parse(body) if err != nil { t.Fatal(err) } if strings.HasPrefix(c.Sources.DropFolder.Path, "~") { t.Errorf("~ not expanded: %q", c.Sources.DropFolder.Path) } if !strings.HasSuffix(c.Sources.DropFolder.Path, "/foo/bar") { t.Errorf("expansion lost suffix: %q", c.Sources.DropFolder.Path) } } func TestParse_RejectsInvalid(t *testing.T) { cases := map[string]string{ "missing agent": `sources:\n webhook:\n routes: {}`, "no sources": `agent: x`, "empty webhook routes": ` agent: x sources: webhook: listen: 127.0.0.1:18790 routes: {} `, "route missing recipient": ` agent: x sources: webhook: routes: /x: type: INFO payload_template: y `, "route missing type": ` agent: x sources: webhook: routes: /x: recipient: r payload_template: y `, "route missing template": ` agent: x sources: webhook: routes: /x: recipient: r type: INFO `, "route path no slash": ` agent: x sources: webhook: routes: bad: recipient: r type: INFO payload_template: y `, "unknown top-level field": ` agent: x typo: oops sources: drop_folder: path: /x `, "poll negative": ` agent: x sources: drop_folder: path: /x poll_fallback_seconds: -1 `, } for name, body := range cases { t.Run(name, func(t *testing.T) { if _, err := parse([]byte(body)); err == nil { t.Errorf("expected error for: %s", name) } }) } } func TestToWebhookRouteMap(t *testing.T) { w := &WebhookConfig{ Routes: map[string]WebhookRoute{ "/x": {Recipient: "r", Type: "INFO", Priority: "urgent", PayloadTemplate: "p"}, }, } got := w.ToWebhookRouteMap() r := got["/x"] if r.Recipient != "r" || r.Type != "INFO" || r.Priority != "urgent" || r.PayloadTemplate != "p" { t.Errorf("conversion lost data: %+v", r) } }