Files
relspecgo/pkg/ui/dataops_test.go
T
warkanum 495a21b67b test: expand coverage across readers, writers, cmd, ui, diff and merge
Implements tests/_plans and previously deferred packages; updates plan
README with new coverage numbers.
2026-10-03 21:33:59 +02:00

199 lines
6.3 KiB
Go

package ui
import (
"reflect"
"testing"
"git.warky.dev/wdevs/relspecgo/pkg/models"
)
func TestColumnDataOps(t *testing.T) {
se := newTestEditor()
if se.CreateColumn(5, 0, "x", "int", false, false) != nil || se.CreateColumn(0, 5, "x", "int", false, false) != nil {
t.Error("create with bad index must return nil")
}
col := se.CreateColumn(0, 0, "age", "integer", true, true)
if col == nil || col.Type != "integer" || !col.IsPrimaryKey || !col.NotNull {
t.Fatalf("create: %+v", col)
}
if se.GetColumn(0, 0, "age") != col || se.GetColumn(0, 0, "nope") != nil || se.GetColumn(9, 0, "age") != nil {
t.Error("get mismatch")
}
if se.CreateColumn(0, 0, "a", "text", false, false) == nil {
t.Error("create second column")
}
tests := []struct {
name string
si, ti int
old, new string
want bool
}{
{"bad table", 0, 9, "age", "age", false},
{"missing column", 0, 0, "zzz", "zzz", false},
{"in place", 0, 0, "age", "age", true},
{"rename", 0, 0, "age", "years", true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := se.UpdateColumn(tt.si, tt.ti, tt.old, tt.new, "bigint", false, true, "0", "desc"); got != tt.want {
t.Errorf("got %v", got)
}
})
}
got := se.GetColumn(0, 0, "years")
if got == nil || got.Name != "years" || got.Type != "bigint" || got.IsPrimaryKey || got.Default != "0" || got.Description != "desc" {
t.Errorf("after update: %+v", got)
}
if se.GetColumn(0, 0, "age") != nil {
t.Error("old name must be gone")
}
if len(se.GetAllColumns(0, 0)) != 4 || se.GetAllColumns(0, 9) != nil {
t.Error("GetAllColumns")
}
if se.DeleteColumn(0, 9, "a") || se.DeleteColumn(0, 0, "zzz") {
t.Error("delete bad target must fail")
}
if !se.DeleteColumn(0, 0, "a") || se.DeleteColumn(0, 0, "a") {
t.Error("delete should succeed once")
}
}
func TestCreateColumn_NilMap(t *testing.T) {
se := newTestEditor()
se.db.Schemas[0].Tables[0].Columns = nil
if se.CreateColumn(0, 0, "a", "text", false, false) == nil {
t.Error("create with nil map")
}
}
func TestRelationshipDataOps(t *testing.T) {
se := newTestEditor()
rel := &models.Relationship{Name: "fk_a", FromTable: "users", ToTable: "orders"}
if se.CreateRelationship(9, 0, rel) != nil || se.CreateRelationship(0, 9, rel) != nil || se.CreateRelationship(0, -1, rel) != nil {
t.Error("create bad index")
}
// Before any relationship exists, update/delete/get/names report nothing.
se.db.Schemas[0].Tables[0].Relationships = nil
if se.UpdateRelationship(0, 0, "fk_a", rel) || se.DeleteRelationship(0, 0, "fk_a") ||
se.GetRelationship(0, 0, "fk_a") != nil || se.GetRelationshipNames(0, 0) != nil {
t.Error("nil map handling")
}
if se.CreateRelationship(0, 0, rel) != rel {
t.Fatal("create")
}
se.CreateRelationship(0, 0, &models.Relationship{Name: "fk_0"})
if got := se.GetRelationshipNames(0, 0); !reflect.DeepEqual(got, []string{"fk_0", "fk_a"}) {
t.Errorf("names must be sorted: %v", got)
}
if se.GetRelationship(0, 0, "fk_a") != rel || se.GetRelationship(0, 0, "none") != nil {
t.Error("get")
}
renamed := &models.Relationship{Name: "fk_b"}
if !se.UpdateRelationship(0, 0, "fk_a", renamed) {
t.Fatal("update")
}
if se.GetRelationship(0, 0, "fk_a") != nil || se.GetRelationship(0, 0, "fk_b") != renamed {
t.Error("rename")
}
if se.UpdateRelationship(9, 0, "x", renamed) || se.UpdateRelationship(0, 9, "x", renamed) {
t.Error("update bad index")
}
if se.DeleteRelationship(9, 0, "x") || se.DeleteRelationship(0, 9, "x") {
t.Error("delete bad index")
}
if !se.DeleteRelationship(0, 0, "fk_b") || se.GetRelationship(0, 0, "fk_b") != nil {
t.Error("delete")
}
if se.GetRelationship(9, 0, "x") != nil || se.GetRelationship(0, 9, "x") != nil ||
se.GetRelationshipNames(9, 0) != nil || se.GetRelationshipNames(0, 9) != nil {
t.Error("bad index reads")
}
}
func TestSchemaDataOps(t *testing.T) {
se := newTestEditor()
s := se.CreateSchema("sales", "desc")
if s == nil || s.Name != "sales" || s.Description != "desc" || s.Tables == nil || s.Sequences == nil || s.Enums == nil {
t.Fatalf("create: %+v", s)
}
if len(se.GetAllSchemas()) != 2 || se.GetSchema(1) != s || se.GetSchema(2) != nil || se.GetSchema(-1) != nil {
t.Error("get")
}
se.UpdateSchema(1, "billing", "owner", "d2")
if s.Name != "billing" || s.Owner != "owner" || s.Description != "d2" {
t.Errorf("update: %+v", s)
}
se.UpdateSchema(9, "x", "x", "x") // no panic
if se.DeleteSchema(9) || se.DeleteSchema(-1) {
t.Error("delete bad index")
}
if !se.DeleteSchema(1) || len(se.db.Schemas) != 1 {
t.Error("delete")
}
}
func TestTableDataOps(t *testing.T) {
se := newTestEditor()
if se.CreateTable(9, "x", "") != nil {
t.Error("create bad schema")
}
tbl := se.CreateTable(0, "orders", "d")
if tbl == nil || tbl.Schema != "public" || tbl.Columns == nil || tbl.Constraints == nil || tbl.Indexes == nil {
t.Fatalf("create: %+v", tbl)
}
if se.GetTable(0, 1) != tbl || se.GetTable(0, 2) != nil || se.GetTable(9, 0) != nil || se.GetTable(0, -1) != nil {
t.Error("get")
}
if len(se.GetAllTables()) != 2 || len(se.GetTablesInSchema(0)) != 2 || se.GetTablesInSchema(9) != nil {
t.Error("get all")
}
se.UpdateTable(0, 1, "orders2", "d2")
if tbl.Name != "orders2" || tbl.Description != "d2" {
t.Errorf("update: %+v", tbl)
}
se.UpdateTable(9, 0, "x", "x")
se.UpdateTable(0, 9, "x", "x")
if se.DeleteTable(9, 0) || se.DeleteTable(0, 9) {
t.Error("delete bad index")
}
if !se.DeleteTable(0, 1) || len(se.db.Schemas[0].Tables) != 1 {
t.Error("delete")
}
}
func TestUpdateDatabase(t *testing.T) {
se := newTestEditor()
se.updateDatabase("n", "d", "c", "pgsql", "16")
db := se.db
if db.Name != "n" || db.Description != "d" || db.Comment != "c" || db.DatabaseType != models.PostgresqlDatabaseType || db.DatabaseVersion != "16" {
t.Errorf("%+v", db)
}
}
func TestDomainDataOps(t *testing.T) {
se := NewSchemaEditor(models.InitDatabase("d"))
se.createDomain("a", "da")
se.createDomain("b", "db")
if len(se.db.Domains) != 2 || se.db.Domains[1].Sequence != 1 {
t.Fatalf("create: %+v", se.db.Domains)
}
se.updateDomain(0, "a2", "da2")
se.updateDomain(9, "x", "x")
if se.db.Domains[0].Name != "a2" || se.db.Domains[0].Description != "da2" {
t.Error("update")
}
se.deleteDomain(9)
se.deleteDomain(-1)
se.deleteDomain(0)
if len(se.db.Domains) != 1 || se.db.Domains[0].Name != "b" {
t.Errorf("delete: %+v", se.db.Domains)
}
}