package config import ( "os" "path/filepath" "strings" "testing" ) func TestLoadSessionWithOptionsRendersCompactPlaceholder(t *testing.T) { dir := t.TempDir() sessionPath := filepath.Join(dir, "session.yml") sessionYAML := `session_id: "{{session_id}}" campaign: sample-campaign inputs: audio_dir: ./audio speakers_file: ./speakers.yml autocorrect_file: ./autocorrect.yml glossary_file: ./glossary.yml ` if err := os.WriteFile(sessionPath, []byte(sessionYAML), 0o644); err != nil { t.Fatalf("write session.yml: %v", err) } cfg, err := LoadSessionWithOptions(sessionPath, SessionLoadOptions{SessionID: "2026-04-04"}) if err != nil { t.Fatalf("LoadSessionWithOptions() error = %v", err) } if cfg.SessionID != "2026-04-04" { t.Fatalf("SessionID = %q, want 2026-04-04", cfg.SessionID) } } func TestLoadSessionWithOptionsRendersSpacedPlaceholder(t *testing.T) { dir := t.TempDir() sessionPath := filepath.Join(dir, "session.yml") sessionYAML := `session_id: "{{ session_id }}" campaign: sample-campaign inputs: audio_dir: ./audio speakers_file: ./speakers.yml autocorrect_file: ./autocorrect.yml glossary_file: ./glossary.yml ` if err := os.WriteFile(sessionPath, []byte(sessionYAML), 0o644); err != nil { t.Fatalf("write session.yml: %v", err) } cfg, err := LoadSessionWithOptions(sessionPath, SessionLoadOptions{SessionID: "2026-04-04"}) if err != nil { t.Fatalf("LoadSessionWithOptions() error = %v", err) } if cfg.SessionID != "2026-04-04" { t.Fatalf("SessionID = %q, want 2026-04-04", cfg.SessionID) } } func TestLoadSessionWithOptionsRendersPreviousSessionPlaceholder(t *testing.T) { dir := t.TempDir() sessionPath := filepath.Join(dir, "session.yml") sessionYAML := `session_id: "{{ session_id }}" previous_session_id: "{{ previous_session_id }}" campaign: sample-campaign inputs: audio_dir: ./audio speakers_file: ./speakers.yml autocorrect_file: ./autocorrect.yml glossary_file: ./glossary.yml ` if err := os.WriteFile(sessionPath, []byte(sessionYAML), 0o644); err != nil { t.Fatalf("write session.yml: %v", err) } cfg, err := LoadSessionWithOptions(sessionPath, SessionLoadOptions{ SessionID: "2026-04-04", PreviousSessionID: "2026-03-28", }) if err != nil { t.Fatalf("LoadSessionWithOptions() error = %v", err) } if cfg.PreviousSessionID != "2026-03-28" { t.Fatalf("PreviousSessionID = %q, want 2026-03-28", cfg.PreviousSessionID) } } func TestLoadSessionWithOptionsUnresolvedPlaceholderFails(t *testing.T) { dir := t.TempDir() sessionPath := filepath.Join(dir, "session.yml") sessionYAML := `session_id: "{{ session_id }}" campaign: sample-campaign inputs: audio_dir: ./audio speakers_file: ./speakers.yml autocorrect_file: ./autocorrect.yml glossary_file: ./glossary.yml ` if err := os.WriteFile(sessionPath, []byte(sessionYAML), 0o644); err != nil { t.Fatalf("write session.yml: %v", err) } _, err := LoadSessionWithOptions(sessionPath, SessionLoadOptions{}) if err == nil { t.Fatal("expected error, got nil") } if !strings.Contains(err.Error(), "unresolved template variable") { t.Fatalf("error = %q, want unresolved-variable context", err.Error()) } if !strings.Contains(err.Error(), "session_id") { t.Fatalf("error = %q, want session_id variable", err.Error()) } } func TestLoadSessionWithOptionsUnresolvedPreviousSessionPlaceholderFails(t *testing.T) { dir := t.TempDir() sessionPath := filepath.Join(dir, "session.yml") sessionYAML := `session_id: 2026-05-03 previous_session_id: "{{ previous_session_id }}" campaign: sample-campaign inputs: audio_dir: ./audio speakers_file: ./speakers.yml autocorrect_file: ./autocorrect.yml glossary_file: ./glossary.yml ` if err := os.WriteFile(sessionPath, []byte(sessionYAML), 0o644); err != nil { t.Fatalf("write session.yml: %v", err) } _, err := LoadSessionWithOptions(sessionPath, SessionLoadOptions{}) if err == nil { t.Fatal("expected error, got nil") } if !strings.Contains(err.Error(), "unresolved template variable") { t.Fatalf("error = %q, want unresolved-variable context", err.Error()) } if !strings.Contains(err.Error(), "previous_session_id") { t.Fatalf("error = %q, want previous_session_id variable", err.Error()) } if !strings.Contains(err.Error(), "--previous-session-id") { t.Fatalf("error = %q, want previous-session-id guidance", err.Error()) } } func TestLoadSessionWithOptionsMismatchFails(t *testing.T) { dir := t.TempDir() sessionPath := filepath.Join(dir, "session.yml") sessionYAML := `session_id: 2026-05-03 campaign: sample-campaign inputs: audio_dir: ./audio speakers_file: ./speakers.yml autocorrect_file: ./autocorrect.yml glossary_file: ./glossary.yml ` if err := os.WriteFile(sessionPath, []byte(sessionYAML), 0o644); err != nil { t.Fatalf("write session.yml: %v", err) } _, err := LoadSessionWithOptions(sessionPath, SessionLoadOptions{SessionID: "2026-04-04"}) if err == nil { t.Fatal("expected error, got nil") } if !strings.Contains(err.Error(), "session_id mismatch") { t.Fatalf("error = %q, want mismatch context", err.Error()) } } func TestLoadSessionWithOptionsPreviousSessionMismatchFails(t *testing.T) { dir := t.TempDir() sessionPath := filepath.Join(dir, "session.yml") sessionYAML := `session_id: 2026-05-03 previous_session_id: 2026-04-26 campaign: sample-campaign inputs: audio_dir: ./audio speakers_file: ./speakers.yml autocorrect_file: ./autocorrect.yml glossary_file: ./glossary.yml ` if err := os.WriteFile(sessionPath, []byte(sessionYAML), 0o644); err != nil { t.Fatalf("write session.yml: %v", err) } _, err := LoadSessionWithOptions(sessionPath, SessionLoadOptions{ SessionID: "2026-05-03", PreviousSessionID: "2026-04-25", }) if err == nil { t.Fatal("expected error, got nil") } if !strings.Contains(err.Error(), "previous_session_id mismatch") { t.Fatalf("error = %q, want mismatch context", err.Error()) } } func TestLoadSessionWithOptionsUnknownFieldStillRejectedAfterRendering(t *testing.T) { dir := t.TempDir() sessionPath := filepath.Join(dir, "session.yml") sessionYAML := `session_id: "{{ session_id }}" campaign: sample-campaign unknown_field: true inputs: audio_dir: ./audio speakers_file: ./speakers.yml autocorrect_file: ./autocorrect.yml glossary_file: ./glossary.yml ` if err := os.WriteFile(sessionPath, []byte(sessionYAML), 0o644); err != nil { t.Fatalf("write session.yml: %v", err) } _, err := LoadSessionWithOptions(sessionPath, SessionLoadOptions{SessionID: "2026-04-04"}) if err == nil { t.Fatal("expected error, got nil") } if !strings.Contains(err.Error(), "strict decode failed") { t.Fatalf("error = %q, want strict-decode context", err.Error()) } } func TestLoadSessionWithOptionsConcreteSessionStillLoads(t *testing.T) { dir := t.TempDir() sessionPath := filepath.Join(dir, "session.yml") sessionYAML := `session_id: 2026-05-03 campaign: sample-campaign inputs: audio_dir: ./audio speakers_file: ./speakers.yml autocorrect_file: ./autocorrect.yml glossary_file: ./glossary.yml ` if err := os.WriteFile(sessionPath, []byte(sessionYAML), 0o644); err != nil { t.Fatalf("write session.yml: %v", err) } cfg, err := LoadSessionWithOptions(sessionPath, SessionLoadOptions{}) if err != nil { t.Fatalf("LoadSessionWithOptions() error = %v", err) } if cfg.SessionID != "2026-05-03" { t.Fatalf("SessionID = %q, want 2026-05-03", cfg.SessionID) } } func TestLoadSessionBytesWithOptionsUsesSameTemplateAndStrictDecode(t *testing.T) { sessionYAML := []byte(`session_id: "{{ session_id }}" campaign: sample-campaign inputs: audio_s3: prefix: audio/ `) cfg, err := LoadSessionBytesWithOptions("s3://bucket/session.yml", sessionYAML, SessionLoadOptions{SessionID: "2026-05-03"}) if err != nil { t.Fatalf("LoadSessionBytesWithOptions() error = %v", err) } if cfg.SessionID != "2026-05-03" { t.Fatalf("SessionID = %q, want 2026-05-03", cfg.SessionID) } _, err = LoadSessionBytesWithOptions("s3://bucket/session.yml", []byte("session_id: 2026-05-03\nunknown: true\n"), SessionLoadOptions{}) if err == nil { t.Fatal("expected strict decode error, got nil") } if !strings.Contains(err.Error(), "strict decode failed") { t.Fatalf("error = %q, want strict decode context", err.Error()) } } func TestLoadSessionBytesWithOptionsMismatchFails(t *testing.T) { _, err := LoadSessionBytesWithOptions("s3://bucket/session.yml", []byte("session_id: 2026-05-03\n"), SessionLoadOptions{SessionID: "2026-04-04"}) if err == nil { t.Fatal("expected mismatch error, got nil") } if !strings.Contains(err.Error(), "session_id mismatch") { t.Fatalf("error = %q, want mismatch context", err.Error()) } }