package render import ( "encoding/json" "strings" "testing" "gitea.maximumdirect.net/eric/seriatim/internal/artifact" "gitea.maximumdirect.net/eric/seriatim/schema" ) func TestFromOutputArtifactNormalizesSupportedSchemas(t *testing.T) { t.Run("full", func(t *testing.T) { sourceIndex := 0 input := schema.Transcript{ Metadata: schema.Metadata{ Application: "seriatim", Version: "v-test", InputReader: "json-files", InputFiles: []string{"a.json"}, PreprocessingModules: []string{"validate-raw"}, PostprocessingModules: []string{"assign-ids", "validate-output"}, OutputModules: []string{"json"}, }, Segments: []schema.Segment{ { ID: 1, Source: "a.json", SourceSegmentIndex: &sourceIndex, Speaker: "Alice", Start: 1, End: 2, Text: "hello", Categories: []string{"background"}, }, }, OverlapGroups: []schema.OverlapGroup{}, } model := mustNormalizeOutputArtifact(t, input) if model.Schema != artifact.OutputSchemaFull { t.Fatalf("schema = %q, want %q", model.Schema, artifact.OutputSchemaFull) } if len(model.Segments) != 1 { t.Fatalf("segment count = %d, want 1", len(model.Segments)) } if model.Segments[0].ID != 1 || model.Segments[0].Speaker != "Alice" || model.Segments[0].Text != "hello" { t.Fatalf("unexpected segment: %#v", model.Segments[0]) } if len(model.Segments[0].Categories) != 1 || model.Segments[0].Categories[0] != "background" { t.Fatalf("categories = %#v, want [background]", model.Segments[0].Categories) } }) t.Run("intermediate", func(t *testing.T) { input := schema.IntermediateTranscript{ Metadata: schema.IntermediateMetadata{ Application: "seriatim", Version: "v-test", OutputSchema: artifact.OutputSchemaIntermediate, }, Segments: []schema.IntermediateSegment{ {ID: 1, Start: 1, End: 2, Speaker: "Alice", Text: "one", Categories: []string{}}, {ID: 2, Start: 2, End: 3, Speaker: "Bob", Text: "two"}, }, } model := mustNormalizeOutputArtifact(t, input) if model.Schema != artifact.OutputSchemaIntermediate { t.Fatalf("schema = %q, want %q", model.Schema, artifact.OutputSchemaIntermediate) } if len(model.Segments[0].Categories) != 0 { t.Fatalf("segment[0] categories = %#v, want empty slice", model.Segments[0].Categories) } if len(model.Segments[1].Categories) != 0 { t.Fatalf("segment[1] categories = %#v, want empty slice", model.Segments[1].Categories) } if model.Segments[0].Categories == nil || model.Segments[1].Categories == nil { t.Fatal("expected non-nil empty categories slices") } }) t.Run("minimal", func(t *testing.T) { input := schema.MinimalTranscript{ Metadata: schema.MinimalMetadata{ Application: "seriatim", Version: "v-test", OutputSchema: artifact.OutputSchemaMinimal, }, Segments: []schema.MinimalSegment{ {ID: 1, Start: 1, End: 2, Speaker: "Alice", Text: "one"}, }, } model := mustNormalizeOutputArtifact(t, input) if model.Schema != artifact.OutputSchemaMinimal { t.Fatalf("schema = %q, want %q", model.Schema, artifact.OutputSchemaMinimal) } if len(model.Segments[0].Categories) != 0 { t.Fatalf("categories = %#v, want empty slice", model.Segments[0].Categories) } if model.Segments[0].Categories == nil { t.Fatal("expected non-nil empty categories slice") } }) } func TestFromOutputArtifactRejectsMalformedAndRawInput(t *testing.T) { _, err := artifact.ParseOutputArtifactJSON([]byte(`{"metadata":`)) if err == nil { t.Fatal("expected malformed JSON error") } if !strings.Contains(err.Error(), "input JSON is malformed") { t.Fatalf("unexpected malformed error: %v", err) } rawWhisper := []byte(`{"segments":[{"id":0,"start":0.1,"end":1.2,"text":"hello","words":[{"word":"hello"}]}]}`) _, err = artifact.ParseOutputArtifactJSON(rawWhisper) if err == nil { t.Fatal("expected raw input artifact error") } if !strings.Contains(err.Error(), "not a valid seriatim output artifact") { t.Fatalf("unexpected raw input error: %v", err) } } func mustNormalizeOutputArtifact(t *testing.T, value any) Transcript { t.Helper() data, err := json.Marshal(value) if err != nil { t.Fatalf("marshal: %v", err) } parsed, err := artifact.ParseOutputArtifactJSON(data) if err != nil { t.Fatalf("parse: %v", err) } model, err := FromOutputArtifact(parsed) if err != nil { t.Fatalf("normalize: %v", err) } return model }