package seriatim import ( "context" "errors" "os" "path/filepath" "strings" "testing" ) func TestFakeRunnerCapturesRequestAndReturnsPath(t *testing.T) { fake := &FakeRunner{} dir := t.TempDir() req := MergeRequest{ GeneratedConfigPath: filepath.Join(dir, "config", "seriatim.yml"), OutputMergedTranscriptPath: filepath.Join(dir, "transcripts", "base.json"), StdoutLogPath: filepath.Join(dir, "logs", "seriatim.stdout.log"), StderrLogPath: filepath.Join(dir, "logs", "seriatim.stderr.log"), } res, err := fake.Run(context.Background(), req) if err != nil { t.Fatalf("Run() error = %v", err) } if len(fake.Requests) != 1 || fake.Requests[0].GeneratedConfigPath == "" { t.Fatalf("requests = %#v, want captured request", fake.Requests) } if res.MergedTranscriptPath != req.OutputMergedTranscriptPath { t.Fatalf("merged path = %q, want %q", res.MergedTranscriptPath, req.OutputMergedTranscriptPath) } cfgData, err := os.ReadFile(req.GeneratedConfigPath) if err != nil { t.Fatalf("read generated config: %v", err) } if !strings.Contains(string(cfgData), "placeholder: true") { t.Fatalf("generated config = %q, want placeholder marker", string(cfgData)) } for _, logPath := range []string{req.StdoutLogPath, req.StderrLogPath} { if _, err := os.Stat(logPath); err != nil { t.Fatalf("expected log file %q to exist: %v", logPath, err) } } } func TestFakeRunnerError(t *testing.T) { fake := &FakeRunner{Err: errors.New("boom")} _, err := fake.Run(context.Background(), MergeRequest{}) if err == nil { t.Fatal("expected error, got nil") } } func TestFakeRunnerTrimCapturesRequestAndReturnsPath(t *testing.T) { fake := &FakeRunner{} dir := t.TempDir() req := TrimRequest{ GeneratedConfigPath: filepath.Join(dir, "config", "seriatim.trim.yml"), InputTranscriptPath: filepath.Join(dir, "transcripts", "polished.json"), OutputTrimmedPath: filepath.Join(dir, "transcripts", "final.trimmed.json"), KeepSelector: "1-10", StdoutLogPath: filepath.Join(dir, "logs", "seriatim.trim.stdout.log"), StderrLogPath: filepath.Join(dir, "logs", "seriatim.trim.stderr.log"), } res, err := fake.Trim(context.Background(), req) if err != nil { t.Fatalf("Trim() error = %v", err) } if len(fake.TrimRequests) != 1 || fake.TrimRequests[0].GeneratedConfigPath == "" { t.Fatalf("trim requests = %#v, want captured request", fake.TrimRequests) } if res.OutputTrimmedPath != req.OutputTrimmedPath { t.Fatalf("trimmed path = %q, want %q", res.OutputTrimmedPath, req.OutputTrimmedPath) } if res.KeepSelector != req.KeepSelector { t.Fatalf("keep selector = %q, want %q", res.KeepSelector, req.KeepSelector) } cfgData, err := os.ReadFile(req.GeneratedConfigPath) if err != nil { t.Fatalf("read generated config: %v", err) } if !strings.Contains(string(cfgData), "command: trim") { t.Fatalf("generated config = %q, want trim command marker", string(cfgData)) } for _, logPath := range []string{req.StdoutLogPath, req.StderrLogPath} { if _, err := os.Stat(logPath); err != nil { t.Fatalf("expected log file %q to exist: %v", logPath, err) } } } func TestFakeRunnerTrimError(t *testing.T) { fake := &FakeRunner{TrimErr: errors.New("boom")} _, err := fake.Trim(context.Background(), TrimRequest{}) if err == nil { t.Fatal("expected error, got nil") } } func TestFakeRunnerNormalizeCapturesRequestAndReturnsPath(t *testing.T) { fake := &FakeRunner{} dir := t.TempDir() req := NormalizeRequest{ GeneratedConfigPath: filepath.Join(dir, "config", "seriatim.normalize.yml"), InputTranscriptPath: filepath.Join(dir, "transcripts", "polished.json"), OutputNormalizedPath: filepath.Join(dir, "transcripts", "final.json"), OutputSchema: "seriatim-intermediate", ReportPath: filepath.Join(dir, "artifacts", "seriatim.normalize.report.json"), StdoutLogPath: filepath.Join(dir, "logs", "seriatim.normalize.stdout.log"), StderrLogPath: filepath.Join(dir, "logs", "seriatim.normalize.stderr.log"), } res, err := fake.Normalize(context.Background(), req) if err != nil { t.Fatalf("Normalize() error = %v", err) } if len(fake.NormalizeRequests) != 1 || fake.NormalizeRequests[0].GeneratedConfigPath == "" { t.Fatalf("normalize requests = %#v, want captured request", fake.NormalizeRequests) } if res.OutputNormalizedPath != req.OutputNormalizedPath { t.Fatalf("normalized path = %q, want %q", res.OutputNormalizedPath, req.OutputNormalizedPath) } if res.OutputSchema != req.OutputSchema { t.Fatalf("output schema = %q, want %q", res.OutputSchema, req.OutputSchema) } cfgData, err := os.ReadFile(req.GeneratedConfigPath) if err != nil { t.Fatalf("read generated config: %v", err) } if !strings.Contains(string(cfgData), "command: normalize") { t.Fatalf("generated config = %q, want normalize command marker", string(cfgData)) } for _, path := range []string{req.StdoutLogPath, req.StderrLogPath, req.ReportPath} { if _, err := os.Stat(path); err != nil { t.Fatalf("expected file %q to exist: %v", path, err) } } } func TestFakeRunnerNormalizeError(t *testing.T) { fake := &FakeRunner{NormalizeErr: errors.New("boom")} _, err := fake.Normalize(context.Background(), NormalizeRequest{}) if err == nil { t.Fatal("expected error, got nil") } } func TestFakeRunnerRenderCapturesRequestAndReturnsPath(t *testing.T) { fake := &FakeRunner{} dir := t.TempDir() req := RenderRequest{ GeneratedConfigPath: filepath.Join(dir, "config", "seriatim.render.yml"), InputTranscriptPath: filepath.Join(dir, "transcripts", "final.trimmed.json"), OutputRenderedPath: filepath.Join(dir, "transcripts", "final.trimmed.md"), Format: "markdown", Title: "Session render", IncludeTimestamps: true, IncludeSegmentIDs: false, IncludeMetadata: true, StdoutLogPath: filepath.Join(dir, "logs", "seriatim.render.stdout.log"), StderrLogPath: filepath.Join(dir, "logs", "seriatim.render.stderr.log"), } res, err := fake.Render(context.Background(), req) if err != nil { t.Fatalf("Render() error = %v", err) } if len(fake.RenderRequests) != 1 || fake.RenderRequests[0].GeneratedConfigPath == "" { t.Fatalf("render requests = %#v, want captured request", fake.RenderRequests) } if res.OutputRenderedPath != req.OutputRenderedPath { t.Fatalf("rendered path = %q, want %q", res.OutputRenderedPath, req.OutputRenderedPath) } if res.Format != req.Format { t.Fatalf("format = %q, want %q", res.Format, req.Format) } if res.Title != req.Title { t.Fatalf("title = %q, want %q", res.Title, req.Title) } cfgData, err := os.ReadFile(req.GeneratedConfigPath) if err != nil { t.Fatalf("read generated config: %v", err) } if !strings.Contains(string(cfgData), "command: render") { t.Fatalf("generated config = %q, want render command marker", string(cfgData)) } for _, path := range []string{req.StdoutLogPath, req.StderrLogPath, req.OutputRenderedPath} { if _, err := os.Stat(path); err != nil { t.Fatalf("expected file %q to exist: %v", path, err) } } } func TestFakeRunnerRenderError(t *testing.T) { fake := &FakeRunner{RenderErr: errors.New("boom")} _, err := fake.Render(context.Background(), RenderRequest{}) if err == nil { t.Fatal("expected error, got nil") } }