package drizzle import ( "os" "path/filepath" "testing" "git.warky.dev/wdevs/relspecgo/pkg/models" "git.warky.dev/wdevs/relspecgo/pkg/readers" ) const fixture = "../../../tests/assets/drizzle/schema.ts" func readFile(t *testing.T, path string) *models.Database { t.Helper() db, err := NewReader(&readers.ReaderOptions{FilePath: path}).ReadDatabase() if err != nil { t.Fatal(err) } return db } func findTable(db *models.Database, name string) *models.Table { for _, s := range db.Schemas { for _, tb := range s.Tables { if tb.Name == name { return tb } } } return nil } func TestReadFixture(t *testing.T) { db := readFile(t, fixture) if len(db.Schemas) == 0 || len(db.Schemas[0].Tables) == 0 { t.Fatal("expected tables") } if len(db.Schemas[0].Enums) != 1 || db.Schemas[0].Enums[0].Name != "Role" { t.Fatalf("enums = %+v", db.Schemas[0].Enums) } var found bool for _, tb := range db.Schemas[0].Tables { if c, ok := tb.Columns["role"]; ok { found = true if c.Type != "Role" { t.Errorf("role type = %q", c.Type) } } for n := range tb.Columns { if n == "profile" { t.Errorf("relation field leaked as column in %s", tb.Name) } } } if !found { t.Error("no role column") } } func TestEnumColumnSyntax(t *testing.T) { tests := []struct { name string src string }{ {"enum constant", "export const role = pgEnum('Role', ['A','B']);\nexport const users = pgTable('users', {\n role: role('role').notNull(),\n});\n"}, {"legacy", "export const role = pgEnum('Role', ['A','B']);\nexport const users = pgTable('users', {\n role: pgEnum('Role')('role').notNull(),\n});\n"}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { p := filepath.Join(t.TempDir(), "s.ts") if err := os.WriteFile(p, []byte(tt.src), 0o644); err != nil { t.Fatal(err) } tb := findTable(readFile(t, p), "users") if tb == nil { t.Fatal("users missing") } c := tb.Columns["role"] if c == nil || c.Type != "Role" || !c.NotNull { t.Errorf("column = %+v", c) } }) } } func TestReadDirectorySeparateEnums(t *testing.T) { dir := t.TempDir() files := map[string]string{ "enums.ts": "export const status = pgEnum('Status', ['on','off']);\n", "tables.ts": "export const items = pgTable('items', {\n status: status('status'),\n});\n", } for n, c := range files { if err := os.WriteFile(filepath.Join(dir, n), []byte(c), 0o644); err != nil { t.Fatal(err) } } tb := findTable(readFile(t, dir), "items") if tb == nil { t.Fatal("items missing") } if c := tb.Columns["status"]; c == nil || c.Type != "Status" { t.Errorf("column = %+v", c) } } func TestReaderErrors(t *testing.T) { if _, err := NewReader(&readers.ReaderOptions{}).ReadDatabase(); err == nil { t.Error("expected error for empty path") } if _, err := NewReader(&readers.ReaderOptions{FilePath: "/nonexistent.ts"}).ReadDatabase(); err == nil { t.Error("expected error for missing file") } }