* Implement tests for error functions like errRequiredField, errInvalidField, and errEntityNotFound. * Ensure proper metadata is returned for various error scenarios. * Validate error handling in CRM, Files, and other tools. * Introduce tests for parsing stored file IDs and UUIDs. * Enhance coverage for helper functions related to project resolution and session management.
108 lines
3.0 KiB
Go
108 lines
3.0 KiB
Go
package tools
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"testing"
|
|
|
|
"git.warky.dev/wdevs/amcs/internal/mcperrors"
|
|
"github.com/modelcontextprotocol/go-sdk/jsonrpc"
|
|
)
|
|
|
|
func TestResolveProjectRequiredErrorGuidesCaller(t *testing.T) {
|
|
_, err := resolveProject(context.Background(), nil, nil, nil, "", true)
|
|
if err == nil {
|
|
t.Fatal("resolveProject() error = nil, want error")
|
|
}
|
|
|
|
rpcErr, data := requireRPCError(t, err)
|
|
if rpcErr.Code != codeProjectRequired {
|
|
t.Fatalf("resolveProject() code = %d, want %d", rpcErr.Code, codeProjectRequired)
|
|
}
|
|
if data.Type != mcperrors.TypeProjectRequired {
|
|
t.Fatalf("resolveProject() type = %q, want %q", data.Type, mcperrors.TypeProjectRequired)
|
|
}
|
|
if data.Field != "project" {
|
|
t.Fatalf("resolveProject() field = %q, want %q", data.Field, "project")
|
|
}
|
|
if data.Hint == "" {
|
|
t.Fatal("resolveProject() hint = empty, want guidance")
|
|
}
|
|
}
|
|
|
|
func TestSessionIDErrorGuidesCaller(t *testing.T) {
|
|
_, err := sessionID(nil)
|
|
if err == nil {
|
|
t.Fatal("sessionID() error = nil, want error")
|
|
}
|
|
|
|
rpcErr, data := requireRPCError(t, err)
|
|
if rpcErr.Code != codeSessionRequired {
|
|
t.Fatalf("sessionID() code = %d, want %d", rpcErr.Code, codeSessionRequired)
|
|
}
|
|
if data.Type != mcperrors.TypeSessionRequired {
|
|
t.Fatalf("sessionID() type = %q, want %q", data.Type, mcperrors.TypeSessionRequired)
|
|
}
|
|
if data.Hint == "" {
|
|
t.Fatal("sessionID() hint = empty, want guidance")
|
|
}
|
|
}
|
|
|
|
func TestParseUUIDReturnsTypedError(t *testing.T) {
|
|
_, err := parseUUID("not-a-uuid")
|
|
if err == nil {
|
|
t.Fatal("parseUUID() error = nil, want error")
|
|
}
|
|
|
|
rpcErr, data := requireRPCError(t, err)
|
|
if rpcErr.Code != codeInvalidID {
|
|
t.Fatalf("parseUUID() code = %d, want %d", rpcErr.Code, codeInvalidID)
|
|
}
|
|
if data.Type != mcperrors.TypeInvalidID {
|
|
t.Fatalf("parseUUID() type = %q, want %q", data.Type, mcperrors.TypeInvalidID)
|
|
}
|
|
if data.Field != "id" {
|
|
t.Fatalf("parseUUID() field = %q, want %q", data.Field, "id")
|
|
}
|
|
if data.Value != "not-a-uuid" {
|
|
t.Fatalf("parseUUID() value = %q, want %q", data.Value, "not-a-uuid")
|
|
}
|
|
if data.Detail == "" {
|
|
t.Fatal("parseUUID() detail = empty, want parse failure detail")
|
|
}
|
|
}
|
|
|
|
func TestErrInvalidInputReturnsTypedError(t *testing.T) {
|
|
err := errInvalidInput("name is required")
|
|
if err == nil {
|
|
t.Fatal("errInvalidInput() error = nil, want error")
|
|
}
|
|
|
|
rpcErr, data := requireRPCError(t, err)
|
|
if rpcErr.Code != jsonrpc.CodeInvalidParams {
|
|
t.Fatalf("errInvalidInput() code = %d, want %d", rpcErr.Code, jsonrpc.CodeInvalidParams)
|
|
}
|
|
if data.Type != mcperrors.TypeInvalidInput {
|
|
t.Fatalf("errInvalidInput() type = %q, want %q", data.Type, mcperrors.TypeInvalidInput)
|
|
}
|
|
}
|
|
|
|
func requireRPCError(t *testing.T, err error) (*jsonrpc.Error, mcpErrorData) {
|
|
t.Helper()
|
|
|
|
var rpcErr *jsonrpc.Error
|
|
if !errors.As(err, &rpcErr) {
|
|
t.Fatalf("error type = %T, want *jsonrpc.Error", err)
|
|
}
|
|
|
|
var data mcpErrorData
|
|
if len(rpcErr.Data) > 0 {
|
|
if unmarshalErr := json.Unmarshal(rpcErr.Data, &data); unmarshalErr != nil {
|
|
t.Fatalf("unmarshal error data: %v", unmarshalErr)
|
|
}
|
|
}
|
|
|
|
return rpcErr, data
|
|
}
|