The old path carried the reachableceo org prefix while the repo lives at
git.knownelement.com/ukrrs/MOPAC; the drift was cited as doc rot. go.mod
and every internal import updated; build/vet/test clean in the builder.
💘 Generated with Crush
Assisted-by: Crush:glm-5.2
92 lines
2.5 KiB
Go
92 lines
2.5 KiB
Go
package intake
|
|
|
|
import (
|
|
"context"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"net/url"
|
|
"testing"
|
|
|
|
"ukrrs.com/mopac/harness/internal/config"
|
|
)
|
|
|
|
func TestListTasks(t *testing.T) {
|
|
var gotPath string
|
|
var gotQuery url.Values
|
|
var gotKey string
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
gotPath = r.URL.Path
|
|
gotQuery = r.URL.Query()
|
|
gotKey = r.Header.Get("X-Redmine-API-Key")
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.Write([]byte(`{
|
|
"issues": [
|
|
{
|
|
"id": 421,
|
|
"subject": "Study crush notes",
|
|
"description": "Read the notes and summarize.",
|
|
"custom_fields": [{"name": "Class", "value": "study"}]
|
|
},
|
|
{
|
|
"id": 422,
|
|
"subject": "No class field",
|
|
"description": ""
|
|
}
|
|
]
|
|
}`))
|
|
}))
|
|
defer srv.Close()
|
|
|
|
cfg := config.RedmineConfig{
|
|
URL: srv.URL,
|
|
ScopeQuery: "project=mopac&status_id=released",
|
|
ClassField: "Class",
|
|
DefaultClass: "primary",
|
|
Limit: 25,
|
|
}
|
|
tasks, err := NewRedmineClient(cfg, "rm-key").ListTasks(context.Background())
|
|
if err != nil {
|
|
t.Fatalf("ListTasks: %v", err)
|
|
}
|
|
if gotPath != "/issues.json" {
|
|
t.Errorf("path = %s", gotPath)
|
|
}
|
|
if gotKey != "rm-key" {
|
|
t.Errorf("API key header = %q", gotKey)
|
|
}
|
|
if gotQuery.Get("project") != "mopac" || gotQuery.Get("limit") != "25" {
|
|
t.Errorf("query = %v", gotQuery)
|
|
}
|
|
if len(tasks) != 2 {
|
|
t.Fatalf("tasks = %d, want 2", len(tasks))
|
|
}
|
|
if tasks[0].ID != "421" || tasks[0].Class != "study" || tasks[0].Source != "redmine" {
|
|
t.Errorf("task0 = %+v", tasks[0])
|
|
}
|
|
// Missing class falls back to default; empty description falls back to subject.
|
|
if tasks[1].Class != "primary" || tasks[1].Prompt != "No class field" {
|
|
t.Errorf("task1 = %+v", tasks[1])
|
|
}
|
|
}
|
|
|
|
func TestListTasksHTTPError(t *testing.T) {
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
http.Error(w, "boom", http.StatusInternalServerError)
|
|
}))
|
|
defer srv.Close()
|
|
cfg := config.RedmineConfig{URL: srv.URL, ScopeQuery: "project=x", ClassField: "Class", DefaultClass: "primary"}
|
|
if _, err := NewRedmineClient(cfg, "k").ListTasks(context.Background()); err == nil {
|
|
t.Fatal("expected HTTP error")
|
|
}
|
|
}
|
|
|
|
func TestDemoTask(t *testing.T) {
|
|
d := config.DemoConfig{
|
|
ID: "demo-1", Subject: "MVP demo", Prompt: "tell me about yourself", Class: "primary",
|
|
}
|
|
tk := DemoTask(d)
|
|
if tk.Source != "demo" || tk.Prompt != "tell me about yourself" || tk.Class != "primary" {
|
|
t.Errorf("DemoTask = %+v", tk)
|
|
}
|
|
}
|