Added Graphql
This commit is contained in:
412
pkg/writers/graphql/writer_test.go
Normal file
412
pkg/writers/graphql/writer_test.go
Normal file
@@ -0,0 +1,412 @@
|
||||
package graphql
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/models"
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/writers"
|
||||
)
|
||||
|
||||
func TestWriter_WriteTable_Simple(t *testing.T) {
|
||||
table := models.InitTable("User", "public")
|
||||
|
||||
idCol := models.InitColumn("id", "User", "public")
|
||||
idCol.Type = "bigint"
|
||||
idCol.IsPrimaryKey = true
|
||||
idCol.NotNull = true
|
||||
table.Columns["id"] = idCol
|
||||
|
||||
nameCol := models.InitColumn("name", "User", "public")
|
||||
nameCol.Type = "text"
|
||||
nameCol.NotNull = true
|
||||
table.Columns["name"] = nameCol
|
||||
|
||||
emailCol := models.InitColumn("email", "User", "public")
|
||||
emailCol.Type = "text"
|
||||
emailCol.NotNull = false
|
||||
table.Columns["email"] = emailCol
|
||||
|
||||
opts := &writers.WriterOptions{
|
||||
OutputPath: "",
|
||||
}
|
||||
|
||||
writer := NewWriter(opts)
|
||||
schema := models.InitSchema("public")
|
||||
schema.Tables = []*models.Table{table}
|
||||
db := models.InitDatabase("test")
|
||||
db.Schemas = []*models.Schema{schema}
|
||||
|
||||
output := writer.databaseToGraphQL(db)
|
||||
|
||||
// Verify output contains type definition
|
||||
if !strings.Contains(output, "type User {") {
|
||||
t.Error("Expected 'type User {' in output")
|
||||
}
|
||||
|
||||
// Verify fields
|
||||
if !strings.Contains(output, "id: ID!") {
|
||||
t.Error("Expected 'id: ID!' in output")
|
||||
}
|
||||
|
||||
if !strings.Contains(output, "name: String!") {
|
||||
t.Error("Expected 'name: String!' in output")
|
||||
}
|
||||
|
||||
if !strings.Contains(output, "email: String") {
|
||||
t.Error("Expected 'email: String' in output")
|
||||
}
|
||||
|
||||
// Ensure email is not followed by ! (nullable)
|
||||
if strings.Contains(output, "email: String!") {
|
||||
t.Error("Did not expect 'email: String!' (should be nullable)")
|
||||
}
|
||||
}
|
||||
|
||||
func TestWriter_WriteDatabase_WithEnum(t *testing.T) {
|
||||
schema := models.InitSchema("public")
|
||||
|
||||
// Create enum
|
||||
roleEnum := &models.Enum{
|
||||
Name: "Role",
|
||||
Schema: "public",
|
||||
Values: []string{"ADMIN", "USER", "GUEST"},
|
||||
}
|
||||
schema.Enums = []*models.Enum{roleEnum}
|
||||
|
||||
// Create table with enum field
|
||||
table := models.InitTable("User", "public")
|
||||
|
||||
idCol := models.InitColumn("id", "User", "public")
|
||||
idCol.Type = "bigint"
|
||||
idCol.IsPrimaryKey = true
|
||||
idCol.NotNull = true
|
||||
table.Columns["id"] = idCol
|
||||
|
||||
roleCol := models.InitColumn("role", "User", "public")
|
||||
roleCol.Type = "Role"
|
||||
roleCol.NotNull = true
|
||||
table.Columns["role"] = roleCol
|
||||
|
||||
schema.Tables = []*models.Table{table}
|
||||
|
||||
db := models.InitDatabase("test")
|
||||
db.Schemas = []*models.Schema{schema}
|
||||
|
||||
opts := &writers.WriterOptions{}
|
||||
writer := NewWriter(opts)
|
||||
|
||||
output := writer.databaseToGraphQL(db)
|
||||
|
||||
// Verify enum definition
|
||||
if !strings.Contains(output, "enum Role {") {
|
||||
t.Error("Expected 'enum Role {' in output")
|
||||
}
|
||||
|
||||
if !strings.Contains(output, "ADMIN") {
|
||||
t.Error("Expected 'ADMIN' enum value in output")
|
||||
}
|
||||
|
||||
// Verify enum usage in type
|
||||
if !strings.Contains(output, "role: Role!") {
|
||||
t.Error("Expected 'role: Role!' in output")
|
||||
}
|
||||
}
|
||||
|
||||
func TestWriter_WriteDatabase_WithRelations(t *testing.T) {
|
||||
schema := models.InitSchema("public")
|
||||
|
||||
// Create User table
|
||||
userTable := models.InitTable("User", "public")
|
||||
userIdCol := models.InitColumn("id", "User", "public")
|
||||
userIdCol.Type = "bigint"
|
||||
userIdCol.IsPrimaryKey = true
|
||||
userIdCol.NotNull = true
|
||||
userTable.Columns["id"] = userIdCol
|
||||
|
||||
userNameCol := models.InitColumn("name", "User", "public")
|
||||
userNameCol.Type = "text"
|
||||
userNameCol.NotNull = true
|
||||
userTable.Columns["name"] = userNameCol
|
||||
|
||||
// Create Post table with FK to User
|
||||
postTable := models.InitTable("Post", "public")
|
||||
|
||||
postIdCol := models.InitColumn("id", "Post", "public")
|
||||
postIdCol.Type = "bigint"
|
||||
postIdCol.IsPrimaryKey = true
|
||||
postIdCol.NotNull = true
|
||||
postTable.Columns["id"] = postIdCol
|
||||
|
||||
titleCol := models.InitColumn("title", "Post", "public")
|
||||
titleCol.Type = "text"
|
||||
titleCol.NotNull = true
|
||||
postTable.Columns["title"] = titleCol
|
||||
|
||||
authorIdCol := models.InitColumn("authorId", "Post", "public")
|
||||
authorIdCol.Type = "bigint"
|
||||
authorIdCol.NotNull = true
|
||||
postTable.Columns["authorId"] = authorIdCol
|
||||
|
||||
// Add FK constraint
|
||||
fkConstraint := models.InitConstraint("fk_post_author", models.ForeignKeyConstraint)
|
||||
fkConstraint.Schema = "public"
|
||||
fkConstraint.Table = "Post"
|
||||
fkConstraint.Columns = []string{"authorId"}
|
||||
fkConstraint.ReferencedSchema = "public"
|
||||
fkConstraint.ReferencedTable = "User"
|
||||
fkConstraint.ReferencedColumns = []string{"id"}
|
||||
postTable.Constraints["fk_post_author"] = fkConstraint
|
||||
|
||||
schema.Tables = []*models.Table{userTable, postTable}
|
||||
|
||||
db := models.InitDatabase("test")
|
||||
db.Schemas = []*models.Schema{schema}
|
||||
|
||||
opts := &writers.WriterOptions{}
|
||||
writer := NewWriter(opts)
|
||||
|
||||
output := writer.databaseToGraphQL(db)
|
||||
|
||||
// Verify Post has author field (forward relationship)
|
||||
if !strings.Contains(output, "author: User!") {
|
||||
t.Error("Expected 'author: User!' in Post type")
|
||||
}
|
||||
|
||||
// Verify authorId FK column is NOT in the output
|
||||
if strings.Contains(output, "authorId:") {
|
||||
t.Error("Did not expect 'authorId:' field in output (FK columns should be hidden)")
|
||||
}
|
||||
|
||||
// Verify User has posts field (reverse relationship)
|
||||
if !strings.Contains(output, "posts: [Post!]!") {
|
||||
t.Error("Expected 'posts: [Post!]!' in User type")
|
||||
}
|
||||
}
|
||||
|
||||
func TestWriter_WriteDatabase_CustomScalars(t *testing.T) {
|
||||
schema := models.InitSchema("public")
|
||||
|
||||
table := models.InitTable("Event", "public")
|
||||
|
||||
idCol := models.InitColumn("id", "Event", "public")
|
||||
idCol.Type = "bigint"
|
||||
idCol.IsPrimaryKey = true
|
||||
idCol.NotNull = true
|
||||
table.Columns["id"] = idCol
|
||||
|
||||
createdAtCol := models.InitColumn("createdAt", "Event", "public")
|
||||
createdAtCol.Type = "timestamp"
|
||||
createdAtCol.NotNull = true
|
||||
table.Columns["createdAt"] = createdAtCol
|
||||
|
||||
metadataCol := models.InitColumn("metadata", "Event", "public")
|
||||
metadataCol.Type = "jsonb"
|
||||
metadataCol.NotNull = false
|
||||
table.Columns["metadata"] = metadataCol
|
||||
|
||||
dateCol := models.InitColumn("eventDate", "Event", "public")
|
||||
dateCol.Type = "date"
|
||||
dateCol.NotNull = false
|
||||
table.Columns["eventDate"] = dateCol
|
||||
|
||||
schema.Tables = []*models.Table{table}
|
||||
|
||||
db := models.InitDatabase("test")
|
||||
db.Schemas = []*models.Schema{schema}
|
||||
|
||||
opts := &writers.WriterOptions{}
|
||||
writer := NewWriter(opts)
|
||||
|
||||
output := writer.databaseToGraphQL(db)
|
||||
|
||||
// Verify scalar declarations
|
||||
if !strings.Contains(output, "scalar DateTime") {
|
||||
t.Error("Expected 'scalar DateTime' declaration")
|
||||
}
|
||||
|
||||
if !strings.Contains(output, "scalar JSON") {
|
||||
t.Error("Expected 'scalar JSON' declaration")
|
||||
}
|
||||
|
||||
if !strings.Contains(output, "scalar Date") {
|
||||
t.Error("Expected 'scalar Date' declaration")
|
||||
}
|
||||
|
||||
// Verify field types
|
||||
if !strings.Contains(output, "createdAt: DateTime!") {
|
||||
t.Error("Expected 'createdAt: DateTime!' in output")
|
||||
}
|
||||
|
||||
if !strings.Contains(output, "metadata: JSON") {
|
||||
t.Error("Expected 'metadata: JSON' in output")
|
||||
}
|
||||
|
||||
if !strings.Contains(output, "eventDate: Date") {
|
||||
t.Error("Expected 'eventDate: Date' in output")
|
||||
}
|
||||
}
|
||||
|
||||
func TestWriter_WriteDatabase_ManyToMany(t *testing.T) {
|
||||
schema := models.InitSchema("public")
|
||||
|
||||
// Create Post table
|
||||
postTable := models.InitTable("Post", "public")
|
||||
postIdCol := models.InitColumn("id", "Post", "public")
|
||||
postIdCol.Type = "bigint"
|
||||
postIdCol.IsPrimaryKey = true
|
||||
postIdCol.NotNull = true
|
||||
postTable.Columns["id"] = postIdCol
|
||||
|
||||
titleCol := models.InitColumn("title", "Post", "public")
|
||||
titleCol.Type = "text"
|
||||
titleCol.NotNull = true
|
||||
postTable.Columns["title"] = titleCol
|
||||
|
||||
// Create Tag table
|
||||
tagTable := models.InitTable("Tag", "public")
|
||||
tagIdCol := models.InitColumn("id", "Tag", "public")
|
||||
tagIdCol.Type = "bigint"
|
||||
tagIdCol.IsPrimaryKey = true
|
||||
tagIdCol.NotNull = true
|
||||
tagTable.Columns["id"] = tagIdCol
|
||||
|
||||
nameCol := models.InitColumn("name", "Tag", "public")
|
||||
nameCol.Type = "text"
|
||||
nameCol.NotNull = true
|
||||
tagTable.Columns["name"] = nameCol
|
||||
|
||||
// Create PostTag join table
|
||||
joinTable := models.InitTable("PostTag", "public")
|
||||
|
||||
postIdJoinCol := models.InitColumn("postId", "PostTag", "public")
|
||||
postIdJoinCol.Type = "bigint"
|
||||
postIdJoinCol.NotNull = true
|
||||
postIdJoinCol.IsPrimaryKey = true
|
||||
joinTable.Columns["postId"] = postIdJoinCol
|
||||
|
||||
tagIdJoinCol := models.InitColumn("tagId", "PostTag", "public")
|
||||
tagIdJoinCol.Type = "bigint"
|
||||
tagIdJoinCol.NotNull = true
|
||||
tagIdJoinCol.IsPrimaryKey = true
|
||||
joinTable.Columns["tagId"] = tagIdJoinCol
|
||||
|
||||
// Add composite PK constraint
|
||||
pkConstraint := models.InitConstraint("pk_posttag", models.PrimaryKeyConstraint)
|
||||
pkConstraint.Schema = "public"
|
||||
pkConstraint.Table = "PostTag"
|
||||
pkConstraint.Columns = []string{"postId", "tagId"}
|
||||
joinTable.Constraints["pk_posttag"] = pkConstraint
|
||||
|
||||
// Add FK to Post
|
||||
fk1 := models.InitConstraint("fk_posttag_post", models.ForeignKeyConstraint)
|
||||
fk1.Schema = "public"
|
||||
fk1.Table = "PostTag"
|
||||
fk1.Columns = []string{"postId"}
|
||||
fk1.ReferencedSchema = "public"
|
||||
fk1.ReferencedTable = "Post"
|
||||
fk1.ReferencedColumns = []string{"id"}
|
||||
joinTable.Constraints["fk_posttag_post"] = fk1
|
||||
|
||||
// Add FK to Tag
|
||||
fk2 := models.InitConstraint("fk_posttag_tag", models.ForeignKeyConstraint)
|
||||
fk2.Schema = "public"
|
||||
fk2.Table = "PostTag"
|
||||
fk2.Columns = []string{"tagId"}
|
||||
fk2.ReferencedSchema = "public"
|
||||
fk2.ReferencedTable = "Tag"
|
||||
fk2.ReferencedColumns = []string{"id"}
|
||||
joinTable.Constraints["fk_posttag_tag"] = fk2
|
||||
|
||||
schema.Tables = []*models.Table{postTable, tagTable, joinTable}
|
||||
|
||||
db := models.InitDatabase("test")
|
||||
db.Schemas = []*models.Schema{schema}
|
||||
|
||||
opts := &writers.WriterOptions{}
|
||||
writer := NewWriter(opts)
|
||||
|
||||
output := writer.databaseToGraphQL(db)
|
||||
|
||||
// Verify join table is NOT in output
|
||||
if strings.Contains(output, "type PostTag") {
|
||||
t.Error("Did not expect 'type PostTag' (join tables should be hidden)")
|
||||
}
|
||||
|
||||
// Verify Post has tags field
|
||||
if !strings.Contains(output, "tags: [Tag!]!") {
|
||||
t.Error("Expected 'tags: [Tag!]!' in Post type")
|
||||
}
|
||||
|
||||
// Verify Tag has posts field
|
||||
if !strings.Contains(output, "posts: [Post!]!") {
|
||||
t.Error("Expected 'posts: [Post!]!' in Tag type")
|
||||
}
|
||||
}
|
||||
|
||||
func TestWriter_WriteDatabase_UUIDType(t *testing.T) {
|
||||
schema := models.InitSchema("public")
|
||||
|
||||
table := models.InitTable("User", "public")
|
||||
|
||||
idCol := models.InitColumn("id", "User", "public")
|
||||
idCol.Type = "uuid"
|
||||
idCol.IsPrimaryKey = true
|
||||
idCol.NotNull = true
|
||||
table.Columns["id"] = idCol
|
||||
|
||||
schema.Tables = []*models.Table{table}
|
||||
|
||||
db := models.InitDatabase("test")
|
||||
db.Schemas = []*models.Schema{schema}
|
||||
|
||||
opts := &writers.WriterOptions{}
|
||||
writer := NewWriter(opts)
|
||||
|
||||
output := writer.databaseToGraphQL(db)
|
||||
|
||||
// UUID primary keys should still map to ID
|
||||
if !strings.Contains(output, "id: ID!") {
|
||||
t.Error("Expected 'id: ID!' for UUID primary key")
|
||||
}
|
||||
}
|
||||
|
||||
func TestWriter_Metadata_NoScalarDeclarations(t *testing.T) {
|
||||
schema := models.InitSchema("public")
|
||||
|
||||
table := models.InitTable("Event", "public")
|
||||
|
||||
idCol := models.InitColumn("id", "Event", "public")
|
||||
idCol.Type = "bigint"
|
||||
idCol.IsPrimaryKey = true
|
||||
table.Columns["id"] = idCol
|
||||
|
||||
createdAtCol := models.InitColumn("createdAt", "Event", "public")
|
||||
createdAtCol.Type = "timestamp"
|
||||
createdAtCol.NotNull = true
|
||||
table.Columns["createdAt"] = createdAtCol
|
||||
|
||||
schema.Tables = []*models.Table{table}
|
||||
|
||||
db := models.InitDatabase("test")
|
||||
db.Schemas = []*models.Schema{schema}
|
||||
|
||||
opts := &writers.WriterOptions{
|
||||
Metadata: map[string]any{
|
||||
"includeScalarDeclarations": false,
|
||||
},
|
||||
}
|
||||
writer := NewWriter(opts)
|
||||
|
||||
output := writer.databaseToGraphQL(db)
|
||||
|
||||
// Verify no scalar declarations
|
||||
if strings.Contains(output, "scalar DateTime") {
|
||||
t.Error("Did not expect 'scalar DateTime' with includeScalarDeclarations=false")
|
||||
}
|
||||
|
||||
// But field should still use DateTime
|
||||
if !strings.Contains(output, "createdAt: DateTime!") {
|
||||
t.Error("Expected 'createdAt: DateTime!' in output")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user