Files
hyperguild/ingestion/internal/api/handler_test.go
Mathias Bergqvist d18fa0dd59 fix(ingestion): validate required query field in Query handler
Empty or whitespace-only queries would silently pass through to search,
returning meaningless results. Also removed the Domain field from
queryRequest — it was accepted but silently ignored since search.Query
has no domain parameter, which would confuse callers.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 20:27:02 +02:00

95 lines
2.7 KiB
Go

// ingestion/internal/api/handler_test.go
package api_test
import (
"bytes"
"encoding/json"
"log/slog"
"net/http"
"net/http/httptest"
"os"
"path/filepath"
"strings"
"testing"
"github.com/mathiasbq/hyperguild/ingestion/internal/api"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func setup(t *testing.T) (string, *api.Handler) {
t.Helper()
dir := t.TempDir()
require.NoError(t, os.MkdirAll(filepath.Join(dir, "wiki", "concepts"), 0o755))
require.NoError(t, os.MkdirAll(filepath.Join(dir, "raw"), 0o755))
require.NoError(t, os.WriteFile(
filepath.Join(dir, "wiki", "concepts", "tdd.md"),
[]byte("---\ntitle: TDD\ndomain: software\n---\n\nTest-driven development is a discipline.\n"),
0o644,
))
logger := slog.New(slog.NewTextHandler(os.Stderr, nil))
return dir, api.NewHandler(dir, logger)
}
func TestQuery_ReturnsResults(t *testing.T) {
_, h := setup(t)
body, _ := json.Marshal(map[string]any{"query": "test driven", "limit": 5})
req := httptest.NewRequest(http.MethodPost, "/query", bytes.NewReader(body))
rec := httptest.NewRecorder()
h.Query(rec, req)
assert.Equal(t, http.StatusOK, rec.Code)
var resp map[string]any
require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp))
results := resp["results"].([]any)
assert.NotEmpty(t, results)
}
func TestWrite_CreatesRawFile(t *testing.T) {
dir, h := setup(t)
body, _ := json.Marshal(map[string]any{
"content": "# Test note\n\nSome content.",
"filename": "test-note.md",
})
req := httptest.NewRequest(http.MethodPost, "/write", bytes.NewReader(body))
rec := httptest.NewRecorder()
h.Write(rec, req)
assert.Equal(t, http.StatusOK, rec.Code)
var resp map[string]string
require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp))
assert.NotEmpty(t, resp["path"])
written := filepath.Join(dir, "raw", "test-note.md")
content, err := os.ReadFile(written)
require.NoError(t, err)
assert.Contains(t, string(content), "Some content.")
}
func TestQuery_RequiresQuery(t *testing.T) {
_, h := setup(t)
body, _ := json.Marshal(map[string]any{"limit": 5})
req := httptest.NewRequest(http.MethodPost, "/query", bytes.NewReader(body))
rec := httptest.NewRecorder()
h.Query(rec, req)
assert.Equal(t, http.StatusBadRequest, rec.Code)
}
func TestWrite_GeneratesFilenameIfAbsent(t *testing.T) {
dir, h := setup(t)
body, _ := json.Marshal(map[string]any{"content": "auto name"})
req := httptest.NewRequest(http.MethodPost, "/write", bytes.NewReader(body))
rec := httptest.NewRecorder()
h.Write(rec, req)
assert.Equal(t, http.StatusOK, rec.Code)
entries, _ := os.ReadDir(filepath.Join(dir, "raw"))
assert.Len(t, entries, 1)
assert.True(t, strings.HasSuffix(entries[0].Name(), ".md"))
}