package main import ( "os" "path/filepath" "strings" "testing" ) func saveBatchState(t *testing.T) { t.Helper() a, b, c, d, e, f, g := batchSourceType, batchInputs, batchTargetType, batchTargetDir, batchPackageName, batchKeepGoing, batchDryRun t.Cleanup(func() { batchSourceType, batchInputs, batchTargetType, batchTargetDir, batchPackageName, batchKeepGoing, batchDryRun = a, b, c, d, e, f, g }) } func TestRunBatch_ConvertsEachInput(t *testing.T) { saveBatchState(t) dir := t.TempDir() writeTestJSON(t, filepath.Join(dir, "a.json"), []string{"users"}) writeTestJSON(t, filepath.Join(dir, "b.json"), []string{"posts"}) outDir := filepath.Join(dir, "out") batchSourceType, batchTargetType, batchTargetDir = "json", "yaml", outDir batchPackageName, batchKeepGoing, batchDryRun = "", false, false batchInputs = []string{filepath.Join(dir, "*.json")} cmd, _ := newDryRunCmd() if err := runBatch(cmd, nil); err != nil { t.Fatalf("batch: %v", err) } for _, name := range []string{"a.yaml", "b.yaml"} { if _, err := os.Stat(filepath.Join(outDir, name)); err != nil { t.Errorf("expected %s: %v", name, err) } } } func TestRunBatch_DryRunWritesNothing(t *testing.T) { saveBatchState(t) dir := t.TempDir() writeTestJSON(t, filepath.Join(dir, "a.json"), []string{"users"}) outDir := filepath.Join(dir, "out") batchSourceType, batchTargetType, batchTargetDir = "json", "yaml", outDir batchPackageName, batchKeepGoing, batchDryRun = "", false, true batchInputs = []string{filepath.Join(dir, "a.json")} cmd, buf := newDryRunCmd() if err := runBatch(cmd, nil); err != nil { t.Fatalf("dry run: %v", err) } if _, err := os.Stat(outDir); !os.IsNotExist(err) { t.Fatal("dry run must not create the output directory") } if !strings.Contains(buf.String(), "users") || !strings.Contains(buf.String(), "a.yaml") { t.Errorf("plan incomplete:\n%s", buf.String()) } } func TestRunBatch_FailureHandling(t *testing.T) { saveBatchState(t) dir := t.TempDir() writeTestJSON(t, filepath.Join(dir, "a.json"), []string{"users"}) if err := os.WriteFile(filepath.Join(dir, "b.json"), []byte("{not json"), 0o644); err != nil { t.Fatal(err) } writeTestJSON(t, filepath.Join(dir, "c.json"), []string{"posts"}) outDir := filepath.Join(dir, "out") batchSourceType, batchTargetType, batchTargetDir = "json", "yaml", outDir batchPackageName, batchDryRun = "", false batchInputs = []string{filepath.Join(dir, "*.json")} cmd, _ := newDryRunCmd() // Default: stop at first failure. batchKeepGoing = false err := runBatch(cmd, nil) if err == nil || !strings.Contains(err.Error(), "b.json") { t.Fatalf("expected failure naming b.json, got %v", err) } if _, statErr := os.Stat(filepath.Join(outDir, "c.yaml")); !os.IsNotExist(statErr) { t.Error("c.json should not be processed without --keep-going") } // --keep-going: remaining inputs are processed, exit still fails. batchKeepGoing = true if err := runBatch(cmd, nil); err == nil { t.Fatal("expected non-zero result with --keep-going") } if _, statErr := os.Stat(filepath.Join(outDir, "c.yaml")); statErr != nil { t.Errorf("c.yaml should be written with --keep-going: %v", statErr) } } func TestExpandBatchInputs(t *testing.T) { dir := t.TempDir() for _, n := range []string{"b.json", "a.json"} { if err := os.WriteFile(filepath.Join(dir, n), []byte("{}"), 0o644); err != nil { t.Fatal(err) } } got, err := expandBatchInputs([]string{filepath.Join(dir, "*.json"), filepath.Join(dir, "a.json")}) if err != nil { t.Fatal(err) } if len(got) != 2 || filepath.Base(got[0]) != "a.json" || filepath.Base(got[1]) != "b.json" { t.Errorf("want sorted deduped [a b], got %v", got) } if _, err := expandBatchInputs([]string{filepath.Join(dir, "*.nope")}); err == nil { t.Error("unmatched pattern should error") } } func TestBatchOutputPaths(t *testing.T) { tests := []struct { name string files []string target string want []string wantErr string }{ {"file target", []string{"x/a.dbml"}, "json", []string{"out/a.json"}, ""}, {"dir target", []string{"x/a.json"}, "gorm", []string{"out/a"}, ""}, {"collision", []string{"x/a.json", "y/a.json"}, "yaml", nil, "both write"}, {"unsupported", []string{"a.json"}, "nope", nil, "unsupported target"}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got, err := batchOutputPaths(tt.files, tt.target, "out") if tt.wantErr != "" { if err == nil || !strings.Contains(err.Error(), tt.wantErr) { t.Fatalf("want error %q, got %v", tt.wantErr, err) } return } if err != nil || len(got) != len(tt.want) || got[0] != filepath.FromSlash(tt.want[0]) { t.Fatalf("got %v, %v; want %v", got, err, tt.want) } }) } }