package graphql import ( "path/filepath" "testing" "git.warky.dev/wdevs/relspecgo/pkg/models" "git.warky.dev/wdevs/relspecgo/pkg/readers" ) func TestReader_ReadDatabase_Simple(t *testing.T) { opts := &readers.ReaderOptions{ FilePath: filepath.Join("..", "..", "..", "tests", "assets", "graphql", "simple.graphql"), } reader := NewReader(opts) db, err := reader.ReadDatabase() if err != nil { t.Fatalf("ReadDatabase() error = %v", err) } if len(db.Schemas) == 0 { t.Fatal("Expected at least one schema") } schema := db.Schemas[0] if schema.Name != "public" { t.Errorf("Expected schema name 'public', got '%s'", schema.Name) } if len(schema.Tables) != 1 { t.Fatalf("Expected 1 table, got %d", len(schema.Tables)) } userTable := schema.Tables[0] if userTable.Name != "User" { t.Errorf("Expected table name 'User', got '%s'", userTable.Name) } // Verify columns expectedColumns := map[string]struct { sqlType string notNull bool isPK bool }{ "id": {"bigint", true, true}, "email": {"text", true, false}, "name": {"text", false, false}, "age": {"integer", false, false}, "active": {"boolean", true, false}, } if len(userTable.Columns) != len(expectedColumns) { t.Fatalf("Expected %d columns, got %d", len(expectedColumns), len(userTable.Columns)) } for colName, expected := range expectedColumns { col, exists := userTable.Columns[colName] if !exists { t.Errorf("Expected column '%s' not found", colName) continue } if col.Type != expected.sqlType { t.Errorf("Column '%s': expected type '%s', got '%s'", colName, expected.sqlType, col.Type) } if col.NotNull != expected.notNull { t.Errorf("Column '%s': expected NotNull=%v, got %v", colName, expected.notNull, col.NotNull) } if col.IsPrimaryKey != expected.isPK { t.Errorf("Column '%s': expected IsPrimaryKey=%v, got %v", colName, expected.isPK, col.IsPrimaryKey) } } } func TestReader_ReadDatabase_WithRelations(t *testing.T) { opts := &readers.ReaderOptions{ FilePath: filepath.Join("..", "..", "..", "tests", "assets", "graphql", "relations.graphql"), } reader := NewReader(opts) db, err := reader.ReadDatabase() if err != nil { t.Fatalf("ReadDatabase() error = %v", err) } schema := db.Schemas[0] if len(schema.Tables) != 2 { t.Fatalf("Expected 2 tables, got %d", len(schema.Tables)) } // Find Post table (should have FK to User) var postTable *models.Table for _, table := range schema.Tables { if table.Name == "Post" { postTable = table break } } if postTable == nil { t.Fatal("Post table not found") } // Verify authorId FK column was created authorIdCol, exists := postTable.Columns["authorId"] if !exists { t.Fatal("Expected 'authorId' FK column not found in Post table") } if authorIdCol.Type != "bigint" { t.Errorf("Expected authorId type 'bigint', got '%s'", authorIdCol.Type) } if !authorIdCol.NotNull { t.Error("Expected authorId to be NOT NULL") } // Verify FK constraint fkConstraintFound := false for _, constraint := range postTable.Constraints { if constraint.Type == models.ForeignKeyConstraint { if constraint.ReferencedTable == "User" && len(constraint.Columns) > 0 && constraint.Columns[0] == "authorId" { fkConstraintFound = true if constraint.OnDelete != "CASCADE" { t.Errorf("Expected OnDelete CASCADE, got %s", constraint.OnDelete) } break } } } if !fkConstraintFound { t.Error("Foreign key constraint from Post to User not found") } } func TestReader_ReadDatabase_WithEnums(t *testing.T) { opts := &readers.ReaderOptions{ FilePath: filepath.Join("..", "..", "..", "tests", "assets", "graphql", "enums.graphql"), } reader := NewReader(opts) db, err := reader.ReadDatabase() if err != nil { t.Fatalf("ReadDatabase() error = %v", err) } schema := db.Schemas[0] if len(schema.Enums) != 1 { t.Fatalf("Expected 1 enum, got %d", len(schema.Enums)) } roleEnum := schema.Enums[0] if roleEnum.Name != "Role" { t.Errorf("Expected enum name 'Role', got '%s'", roleEnum.Name) } expectedValues := []string{"ADMIN", "USER", "GUEST"} if len(roleEnum.Values) != len(expectedValues) { t.Fatalf("Expected %d enum values, got %d", len(expectedValues), len(roleEnum.Values)) } for i, expected := range expectedValues { if roleEnum.Values[i] != expected { t.Errorf("Expected enum value '%s' at index %d, got '%s'", expected, i, roleEnum.Values[i]) } } // Verify role column in User table userTable := schema.Tables[0] roleCol, exists := userTable.Columns["role"] if !exists { t.Fatal("Expected 'role' column not found") } if roleCol.Type != "Role" { t.Errorf("Expected role type 'Role', got '%s'", roleCol.Type) } } func TestReader_ReadDatabase_CustomScalars(t *testing.T) { opts := &readers.ReaderOptions{ FilePath: filepath.Join("..", "..", "..", "tests", "assets", "graphql", "custom_scalars.graphql"), } reader := NewReader(opts) db, err := reader.ReadDatabase() if err != nil { t.Fatalf("ReadDatabase() error = %v", err) } schema := db.Schemas[0] userTable := schema.Tables[0] // Verify custom scalar mappings expectedTypes := map[string]string{ "createdAt": "timestamp", "metadata": "jsonb", "birthDate": "date", } for colName, expectedType := range expectedTypes { col, exists := userTable.Columns[colName] if !exists { t.Errorf("Expected column '%s' not found", colName) continue } if col.Type != expectedType { t.Errorf("Column '%s': expected type '%s', got '%s'", colName, expectedType, col.Type) } } } func TestReader_ReadDatabase_UUIDMetadata(t *testing.T) { opts := &readers.ReaderOptions{ FilePath: filepath.Join("..", "..", "..", "tests", "assets", "graphql", "simple.graphql"), Metadata: map[string]interface{}{ "idType": "uuid", }, } reader := NewReader(opts) db, err := reader.ReadDatabase() if err != nil { t.Fatalf("ReadDatabase() error = %v", err) } schema := db.Schemas[0] userTable := schema.Tables[0] idCol, exists := userTable.Columns["id"] if !exists { t.Fatal("Expected 'id' column not found") } if idCol.Type != "uuid" { t.Errorf("Expected id type 'uuid' with metadata, got '%s'", idCol.Type) } } func TestReader_ReadDatabase_Complex(t *testing.T) { opts := &readers.ReaderOptions{ FilePath: filepath.Join("..", "..", "..", "tests", "assets", "graphql", "complex.graphql"), } reader := NewReader(opts) db, err := reader.ReadDatabase() if err != nil { t.Fatalf("ReadDatabase() error = %v", err) } schema := db.Schemas[0] // Should have 5 tables: User, Profile, Post, Tag, and PostTag (join table) expectedTableCount := 5 if len(schema.Tables) != expectedTableCount { t.Fatalf("Expected %d tables, got %d", expectedTableCount, len(schema.Tables)) } // Verify PostTag join table exists (many-to-many between Post and Tag) var joinTable *models.Table for _, table := range schema.Tables { if table.Name == "PostTag" { joinTable = table break } } if joinTable == nil { t.Fatal("Expected PostTag join table not found") } // Verify join table has both FK columns if _, exists := joinTable.Columns["postId"]; !exists { t.Error("Expected 'postId' column in PostTag join table") } if _, exists := joinTable.Columns["tagId"]; !exists { t.Error("Expected 'tagId' column in PostTag join table") } // Verify composite primary key pkFound := false for _, constraint := range joinTable.Constraints { if constraint.Type == models.PrimaryKeyConstraint { if len(constraint.Columns) == 2 { pkFound = true } break } } if !pkFound { t.Error("Expected composite primary key in PostTag join table") } } func TestReader_ReadSchema(t *testing.T) { opts := &readers.ReaderOptions{ FilePath: filepath.Join("..", "..", "..", "tests", "assets", "graphql", "simple.graphql"), } reader := NewReader(opts) schema, err := reader.ReadSchema() if err != nil { t.Fatalf("ReadSchema() error = %v", err) } if schema.Name != "public" { t.Errorf("Expected schema name 'public', got '%s'", schema.Name) } if len(schema.Tables) != 1 { t.Errorf("Expected 1 table, got %d", len(schema.Tables)) } } func TestReader_ReadTable(t *testing.T) { opts := &readers.ReaderOptions{ FilePath: filepath.Join("..", "..", "..", "tests", "assets", "graphql", "simple.graphql"), } reader := NewReader(opts) table, err := reader.ReadTable() if err != nil { t.Fatalf("ReadTable() error = %v", err) } if table.Name != "User" { t.Errorf("Expected table name 'User', got '%s'", table.Name) } } func TestReader_InvalidPath(t *testing.T) { opts := &readers.ReaderOptions{ FilePath: "/nonexistent/path.graphql", } reader := NewReader(opts) _, err := reader.ReadDatabase() if err == nil { t.Error("Expected error for invalid path, got nil") } } func TestReader_EmptyPath(t *testing.T) { opts := &readers.ReaderOptions{ FilePath: "", } reader := NewReader(opts) _, err := reader.ReadDatabase() if err == nil { t.Error("Expected error for empty path, got nil") } }