Files
scriptorium/internal/format/prepared_run_test.go

188 lines
5.4 KiB
Go

package format
import (
"encoding/json"
"errors"
"strings"
"testing"
"gitea.maximumdirect.net/eric/scriptorium/internal/domain"
)
func TestTextFormatterIncludesPreparedRunDetails(t *testing.T) {
prepared := samplePreparedRun()
out, err := FormatPreparedRun(prepared, PreparedRunFormatText)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
s := string(out)
for _, want := range []string{
"prompt: prompt.id",
"prompt_version: v1",
"selected_profile_id: local-fast",
"endpoint: http://llm/v1",
"model: gpt-test",
"temperature: 0.4",
"max_tokens: 256",
"top_p: 0.8",
"timeout_seconds: 45",
"service_tier: priority",
"reasoning_effort: medium",
"api_key_env: SCRIPTORIUM_API_KEY",
"prompt_hash: prompt-hash",
"rendered_prompt_hash: rendered-hash",
"glossary: hash-glossary",
"transcript: hash-transcript",
"messages:",
" system:",
" user:",
"System guidance.",
"Summarize the transcript.",
"Include key entities.",
"Second user message.",
} {
if !strings.Contains(s, want) {
t.Fatalf("expected text output to include %q, got:\n%s", want, s)
}
}
}
func TestTextFormatterDoesNotIncludeResolvedAPIKeyValue(t *testing.T) {
const secret = "super-secret-api-key"
t.Setenv("SCRIPTORIUM_API_KEY", secret)
out, err := FormatPreparedRun(samplePreparedRun(), PreparedRunFormatText)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
if strings.Contains(string(out), secret) {
t.Fatalf("text output should not include resolved api key value: %s", out)
}
}
func TestJSONFormatterEmitsValidJSONAndIncludesPreparedRunFields(t *testing.T) {
prepared := samplePreparedRun()
out, err := FormatPreparedRun(prepared, PreparedRunFormatJSON)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
var decoded map[string]any
if err := json.Unmarshal(out, &decoded); err != nil {
t.Fatalf("expected valid json output, got %v", err)
}
if decoded["prompt_id"] != "prompt.id" {
t.Fatalf("expected prompt_id in json output, got %#v", decoded["prompt_id"])
}
if decoded["prompt_version"] != "v1" {
t.Fatalf("expected prompt_version in json output, got %#v", decoded["prompt_version"])
}
if decoded["selected_profile_id"] != "local-fast" {
t.Fatalf("expected selected_profile_id in json output, got %#v", decoded["selected_profile_id"])
}
if decoded["rendered_prompt_hash"] != "rendered-hash" {
t.Fatalf("expected rendered_prompt_hash in json output, got %#v", decoded["rendered_prompt_hash"])
}
if _, ok := decoded["effective_model_params"]; !ok {
t.Fatalf("expected effective_model_params in json output, got %#v", decoded)
}
if _, ok := decoded["input_hashes"]; !ok {
t.Fatalf("expected input_hashes in json output, got %#v", decoded)
}
if _, ok := decoded["messages"]; !ok {
t.Fatalf("expected messages in json output, got %#v", decoded)
}
}
func TestJSONFormatterDoesNotIncludeResolvedAPIKeyValue(t *testing.T) {
const secret = "super-secret-api-key"
t.Setenv("SCRIPTORIUM_API_KEY", secret)
out, err := FormatPreparedRun(samplePreparedRun(), PreparedRunFormatJSON)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
if strings.Contains(string(out), secret) {
t.Fatalf("json output should not include resolved api key value: %s", out)
}
}
func TestParsePreparedRunOutputFormatRecognizesSupportedNames(t *testing.T) {
tests := []struct {
name string
input string
want PreparedRunOutputFormat
}{
{name: "default empty", input: "", want: DefaultPreparedRunOutputFormat},
{name: "text", input: "text", want: PreparedRunFormatText},
{name: "json", input: "json", want: PreparedRunFormatJSON},
{name: "trim and case", input: " JSON ", want: PreparedRunFormatJSON},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
got, err := ParsePreparedRunOutputFormat(tc.input)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
if got != tc.want {
t.Fatalf("expected %q, got %q", tc.want, got)
}
})
}
}
func TestParsePreparedRunOutputFormatUnknownFails(t *testing.T) {
_, err := ParsePreparedRunOutputFormat("yaml")
if err == nil {
t.Fatal("expected error for unknown format")
}
if !errors.Is(err, ErrUnknownPreparedRunFormat) {
t.Fatalf("expected ErrUnknownPreparedRunFormat, got %v", err)
}
}
func TestFormatPreparedRunByNameUnknownFailsClearly(t *testing.T) {
_, err := FormatPreparedRunByName(samplePreparedRun(), "yaml")
if err == nil {
t.Fatal("expected unknown format error")
}
if !errors.Is(err, ErrUnknownPreparedRunFormat) {
t.Fatalf("expected ErrUnknownPreparedRunFormat, got %v", err)
}
}
func samplePreparedRun() *domain.PreparedRun {
return &domain.PreparedRun{
PromptID: "prompt.id",
PromptVersion: "v1",
PromptHash: "prompt-hash",
SelectedProfileID: "local-fast",
EffectiveModelParams: domain.ExecutionTarget{
Endpoint: "http://llm/v1",
Model: "gpt-test",
Temperature: 0.4,
MaxTokens: 256,
TopP: 0.8,
TimeoutSeconds: 45,
ServiceTier: "priority",
ReasoningEffort: "medium",
APIKeyEnv: "SCRIPTORIUM_API_KEY",
},
InputHashes: map[string]string{
"transcript": "hash-transcript",
"glossary": "hash-glossary",
},
RenderedPromptHash: "rendered-hash",
Messages: []domain.RenderedMessage{
{Role: "system", Content: "System guidance."},
{Role: "user", Content: "Summarize the transcript.\nInclude key entities."},
{Role: "user", Content: "Second user message."},
},
}
}