package dctx import ( "encoding/xml" "os" "testing" "git.warky.dev/wdevs/relspecgo/pkg/models" "git.warky.dev/wdevs/relspecgo/pkg/writers" "github.com/stretchr/testify/assert" ) func TestWriter_WriteSchema(t *testing.T) { // 1. Create a sample schema schema := models.InitSchema("public") schema.Name = "TestDB" // Table 1: users usersTable := models.InitTable("users", "public") usersTable.Comment = "Stores user information" idCol := models.InitColumn("id", "users", "public") idCol.Type = "serial" idCol.IsPrimaryKey = true usersTable.Columns["id"] = idCol nameCol := models.InitColumn("name", "users", "public") nameCol.Type = "varchar" nameCol.Length = 100 usersTable.Columns["name"] = nameCol pkIndex := models.InitIndex("users_pkey", "users", "public") pkIndex.Unique = true pkIndex.Columns = []string{"id"} usersTable.Indexes["users_pkey"] = pkIndex schema.Tables = append(schema.Tables, usersTable) // Table 2: posts postsTable := models.InitTable("posts", "public") postsTable.Comment = "Stores blog posts" postIDCol := models.InitColumn("id", "posts", "public") postIDCol.Type = "serial" postIDCol.IsPrimaryKey = true postsTable.Columns["id"] = postIDCol titleCol := models.InitColumn("title", "posts", "public") titleCol.Type = "varchar" titleCol.Length = 255 postsTable.Columns["title"] = titleCol userIDCol := models.InitColumn("user_id", "posts", "public") userIDCol.Type = "integer" postsTable.Columns["user_id"] = userIDCol postsPKIndex := models.InitIndex("posts_pkey", "posts", "public") postsPKIndex.Unique = true postsPKIndex.Columns = []string{"id"} postsTable.Indexes["posts_pkey"] = postsPKIndex fkIndex := models.InitIndex("posts_user_id_idx", "posts", "public") fkIndex.Columns = []string{"user_id"} postsTable.Indexes["posts_user_id_idx"] = fkIndex schema.Tables = append(schema.Tables, postsTable) // Constraint for the relationship fkConstraint := models.InitConstraint("fk_posts_users", models.ForeignKeyConstraint) fkConstraint.Table = "posts" fkConstraint.Schema = "public" fkConstraint.Columns = []string{"user_id"} fkConstraint.ReferencedTable = "users" fkConstraint.ReferencedSchema = "public" fkConstraint.ReferencedColumns = []string{"id"} postsTable.Constraints["fk_posts_users"] = fkConstraint // Relation relation := models.InitRelation("fk_posts_users", "public") relation.FromTable = "posts" relation.ToTable = "users" relation.ForeignKey = "fk_posts_users" schema.Relations = append(schema.Relations, relation) // 2. Setup writer outputPath := "/tmp/test.dctx" opts := &writers.WriterOptions{ OutputPath: outputPath, } writer := NewWriter(opts) // 3. Write the schema err := writer.WriteSchema(schema) assert.NoError(t, err) // 4. Read the file and unmarshal it actualBytes, err := os.ReadFile(outputPath) assert.NoError(t, err) var dctx models.DCTXDictionary err = xml.Unmarshal(actualBytes, &dctx) assert.NoError(t, err) // 5. Assert properties of the unmarshaled struct assert.Equal(t, "TestDB", dctx.Name) assert.Equal(t, "1", dctx.Version) assert.Len(t, dctx.Tables, 2) assert.Len(t, dctx.Relations, 1) // Assert users table usersTableResult := dctx.Tables[0] assert.Equal(t, "users", usersTableResult.Name) assert.Len(t, usersTableResult.Fields, 2) assert.Len(t, usersTableResult.Keys, 1) userPK := usersTableResult.Keys[0] assert.True(t, userPK.Primary) assert.Equal(t, "users_pkey", userPK.Name) assert.Len(t, userPK.Components, 1) userPKComponent := userPK.Components[0] assert.NotEmpty(t, userPKComponent.FieldId) // Assert posts table postsTableResult := dctx.Tables[1] assert.Equal(t, "posts", postsTableResult.Name) assert.Len(t, postsTableResult.Fields, 3) assert.Len(t, postsTableResult.Keys, 2) postsFK := postsTableResult.Keys[1] // Assuming order assert.False(t, postsFK.Primary) assert.Equal(t, "posts_user_id_idx", postsFK.Name) assert.Len(t, postsFK.Components, 1) postsFKComponent := postsFK.Components[0] assert.NotEmpty(t, postsFKComponent.FieldId) // Assert relation relationResult := dctx.Relations[0] // PrimaryTable and ForeignTable should be GUIDs in DCTX format assert.NotEmpty(t, relationResult.PrimaryTable, "PrimaryTable should have a GUID") assert.NotEmpty(t, relationResult.ForeignTable, "ForeignTable should have a GUID") assert.NotEmpty(t, relationResult.PrimaryKey) assert.NotEmpty(t, relationResult.ForeignKey) // Check if the table GUIDs match assert.Equal(t, usersTableResult.Guid, relationResult.PrimaryTable, "PrimaryTable GUID should match users table") assert.Equal(t, postsTableResult.Guid, relationResult.ForeignTable, "ForeignTable GUID should match posts table") // Check if the key GUIDs match up assert.Equal(t, userPK.Guid, relationResult.PrimaryKey) assert.Equal(t, postsFK.Guid, relationResult.ForeignKey) // Verify field mappings exist assert.NotEmpty(t, relationResult.ForeignMappings, "Relation should have ForeignMappings") assert.NotEmpty(t, relationResult.PrimaryMappings, "Relation should have PrimaryMappings") // ForeignMapping should reference primary table (users) fields assert.Len(t, relationResult.ForeignMappings, 1) assert.NotEmpty(t, relationResult.ForeignMappings[0].Field) // PrimaryMapping should reference foreign table (posts) fields assert.Len(t, relationResult.PrimaryMappings, 1) assert.NotEmpty(t, relationResult.PrimaryMappings[0].Field) }