Files
scriptorium/internal/usecase/integration_test.go

100 lines
3.2 KiB
Go

package usecase
import (
"context"
"path/filepath"
"testing"
"gitea.maximumdirect.net/eric/scriptorium/internal/artifact"
"gitea.maximumdirect.net/eric/scriptorium/internal/domain"
"gitea.maximumdirect.net/eric/scriptorium/internal/profile"
"gitea.maximumdirect.net/eric/scriptorium/internal/prompt"
"gitea.maximumdirect.net/eric/scriptorium/internal/validate"
)
type integrationLLM struct{}
func (f *integrationLLM) Generate(ctx context.Context, req domain.GenerateRequest) (*domain.GenerateResponse, error) {
return &domain.GenerateResponse{
Content: `{"summary":"Party discovered a captive scout beneath the tower.","events":[{"title":"Scout found in cellar","type":"discovery","notes":"Scout requested rescue from goblin raiders."}]}`,
Usage: domain.TokenUsage{
PromptTokens: 42,
CompletionTokens: 36,
TotalTokens: 78,
},
}, nil
}
func TestRunnerIntegrationWithProfilesFixturesAndValidation(t *testing.T) {
root, err := filepath.Abs(filepath.Join("..", ".."))
if err != nil {
t.Fatalf("failed to resolve repo root: %v", err)
}
profilesDir := filepath.Join(root, "profiles")
schemasDir := filepath.Join(root, "schemas")
fixturesDir := filepath.Join(root, "examples", "fixtures")
runner := NewRunner(
profile.NewFilesystemRepository(profilesDir),
artifact.NewCompositeReader(),
prompt.NewGoRenderer(),
&integrationLLM{},
validate.NewStandardValidator(schemasDir),
)
res, err := runner.Run(context.Background(), domain.RunRequest{
ProfileID: "generic.structured_events",
Inputs: map[string]domain.ArtifactRef{
"transcript": {
Type: domain.ArtifactRefFile,
URI: filepath.Join(fixturesDir, "transcript.md"),
},
"glossary": {
Type: domain.ArtifactRefFile,
URI: filepath.Join(fixturesDir, "glossary.yml"),
},
},
})
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
if res.ProfileID != "generic.structured_events" {
t.Fatalf("unexpected profile id: %q", res.ProfileID)
}
if res.ProfileVersion != "1.0.0" {
t.Fatalf("unexpected profile version: %q", res.ProfileVersion)
}
if res.Validation.Status != domain.ValidationPassed {
t.Fatalf("expected passed validation, got %q", res.Validation.Status)
}
if res.Validation.Mode != domain.ValidationJSONSchema {
t.Fatalf("expected json_schema mode, got %q", res.Validation.Mode)
}
if res.Artifact.ContentType != "application/json" {
t.Fatalf("expected application/json output, got %q", res.Artifact.ContentType)
}
if len(res.RawOutput) == 0 {
t.Fatal("expected raw output to be preserved")
}
if res.PromptHash == "" {
t.Fatal("expected non-empty prompt hash")
}
if len(res.InputHashes) != 2 {
t.Fatalf("expected two input hashes, got %d", len(res.InputHashes))
}
if res.InputHashes["transcript"] == "" || res.InputHashes["glossary"] == "" {
t.Fatalf("expected both input hashes to be set, got %#v", res.InputHashes)
}
if res.Usage.TotalTokens != 78 {
t.Fatalf("expected usage from fake llm, got %+v", res.Usage)
}
if res.StartTime.IsZero() || res.EndTime.IsZero() {
t.Fatal("expected start/end timestamps")
}
if res.EndTime.Before(res.StartTime) {
t.Fatalf("expected end >= start, got start=%v end=%v", res.StartTime, res.EndTime)
}
}