// internal/skills/spec/handlers_test.go package spec_test import ( "context" "encoding/json" "testing" "github.com/mathiasbq/supervisor/internal/skills/spec" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestSpecToolRegistered(t *testing.T) { sk := spec.New(spec.Config{SkillPrompt: "spec rules"}) names := make([]string, 0) for _, tool := range sk.Tools() { names = append(names, tool.Name) } assert.Contains(t, names, "spec") } func TestSpecRequiresProjectRoot(t *testing.T) { sk := spec.New(spec.Config{SkillPrompt: "s"}) _, err := sk.Handle(context.Background(), "spec", json.RawMessage(`{"requirements":"add login"}`)) assert.ErrorContains(t, err, "project_root") } func TestSpecRequiresRequirements(t *testing.T) { sk := spec.New(spec.Config{SkillPrompt: "s"}) _, err := sk.Handle(context.Background(), "spec", json.RawMessage(`{"project_root":"/tmp"}`)) assert.ErrorContains(t, err, "requirements") } func TestSpecCallsCompleteFunc(t *testing.T) { var capturedTask string fakeFn := func(_ context.Context, _, _, user string) (string, int64, error) { capturedTask = user return "# OAuth2 Login Spec\n\n## Overview\nImplement OAuth2 login flow.", 110, nil } sk := spec.New(spec.Config{SkillPrompt: "spec rules", CompleteFunc: fakeFn, SessionsDir: t.TempDir()}) out, err := sk.Handle(context.Background(), "spec", json.RawMessage( `{"project_root":"/tmp/proj","requirements":"add OAuth2 login","output_path":"docs/login-spec.md"}`, )) require.NoError(t, err) assert.Contains(t, capturedTask, "OAuth2 login") assert.Contains(t, capturedTask, "docs/login-spec.md") var result map[string]any require.NoError(t, json.Unmarshal(out, &result)) assert.Contains(t, result["text"], "OAuth2 Login Spec") }