test(09-03): add failing tests for Winter admin controller scaffolding

- make:admin-controller must emit config_form and config_list beside model fields and columns
- A pre-existing model asset must fail before any controller file is written
This commit is contained in:
Jakub Zych
2026-09-24 18:24:06 +02:00
parent da8828ef38
commit af8e58a038
2 changed files with 161 additions and 0 deletions

View File

@@ -8,6 +8,9 @@ import (
"strconv"
"strings"
"testing"
"git.golem15.com/golem15/summercms/cabana"
"git.golem15.com/golem15/summercms/pact"
)
func TestLoadHelloManifest(t *testing.T) {
@@ -878,6 +881,159 @@ func TestMakeArtifactRejectsMalformedNames(t *testing.T) {
}
}
func TestMakeAdminControllerLayout(t *testing.T) {
dir := copyHelloApp(t)
ctx := t.Context()
pluginDir, err := MakePlugin(ctx, dir, "golem15.demo")
if err != nil {
t.Fatal(err)
}
pluginBefore, err := os.ReadFile(filepath.Join(pluginDir, "plugin.go"))
if err != nil {
t.Fatal(err)
}
t.Run("duplicate asset writes nothing", func(t *testing.T) {
kept := filepath.Join(pluginDir, "models", "genres", "fields.yaml")
if err := os.MkdirAll(filepath.Dir(kept), 0o755); err != nil {
t.Fatal(err)
}
const original = "fields: {}\n"
if err := os.WriteFile(kept, []byte(original), 0o644); err != nil {
t.Fatal(err)
}
if _, err := MakeAdminController(ctx, dir, "golem15.demo", "Genres"); err == nil {
t.Fatal("duplicate model asset want error")
}
body, err := os.ReadFile(kept)
if err != nil || string(body) != original {
t.Fatalf("existing fields.yaml changed: %v %q", err, body)
}
for _, rel := range []string{
filepath.Join("controllers", "genres.go"),
filepath.Join("controllers", "genres", "config_form.yaml"),
filepath.Join("controllers", "genres", "config_list.yaml"),
filepath.Join("models", "genres", "columns.yaml"),
} {
if _, err := os.Stat(filepath.Join(pluginDir, rel)); !os.IsNotExist(err) {
t.Fatalf("partial scaffold file %s err=%v", rel, err)
}
}
})
t.Run("winter files", func(t *testing.T) {
admin, err := MakeAdminController(ctx, dir, "golem15.demo", "Albums")
if err != nil {
t.Fatal(err)
}
want := []string{
filepath.Join(pluginDir, "controllers", "albums.go"),
filepath.Join(pluginDir, "controllers", "albums", "config_form.yaml"),
filepath.Join(pluginDir, "controllers", "albums", "config_list.yaml"),
filepath.Join(pluginDir, "models", "albums", "fields.yaml"),
filepath.Join(pluginDir, "models", "albums", "columns.yaml"),
}
if strings.Join(admin.Files, "\n") != strings.Join(want, "\n") {
t.Fatalf("files =\n%s\nwant\n%s", strings.Join(admin.Files, "\n"), strings.Join(want, "\n"))
}
for _, rel := range []string{
filepath.Join("controllers", "albums", "fields.yaml"),
filepath.Join("controllers", "albums", "columns.yaml"),
} {
if _, err := os.Stat(filepath.Join(pluginDir, rel)); !os.IsNotExist(err) {
t.Fatalf("old controller-local asset %s still exists", rel)
}
}
goSrc, err := os.ReadFile(want[0])
if err != nil {
t.Fatal(err)
}
for _, text := range []string{
`ID() string { return "golem15.demo.albums" }`,
`ModelName() string { return "Albums" }`,
`ConfigDir() string { return "controllers/albums" }`,
} {
if !bytes.Contains(goSrc, []byte(text)) {
t.Fatalf("albums.go missing %s:\n%s", text, goSrc)
}
}
formSrc, err := os.ReadFile(want[1])
if err != nil {
t.Fatal(err)
}
for _, text := range []string{
"modelClass: Albums",
"form: ~/plugins/golem15/demo/models/albums/fields.yaml",
} {
if !bytes.Contains(formSrc, []byte(text)) {
t.Fatalf("config_form.yaml missing %s:\n%s", text, formSrc)
}
}
listSrc, err := os.ReadFile(want[2])
if err != nil {
t.Fatal(err)
}
for _, text := range []string{
"modelClass: Albums",
"list: ~/plugins/golem15/demo/models/albums/columns.yaml",
} {
if !bytes.Contains(listSrc, []byte(text)) {
t.Fatalf("config_list.yaml missing %s:\n%s", text, listSrc)
}
}
fsys := os.DirFS(pluginDir)
ctl := scaffoldAlbumsController{}
if _, err := cabana.CompileForm("golem15.demo", ctl, fsys); err != nil {
t.Fatalf("strict form compile: %v", err)
}
if _, err := cabana.CompileList("golem15.demo", ctl, fsys); err != nil {
t.Fatalf("strict list compile: %v", err)
}
reg1, err := os.ReadFile(filepath.Join(pluginDir, "registry.gen.go"))
if err != nil {
t.Fatal(err)
}
if !bytes.Contains(reg1, []byte("controllers.AlbumsController()")) {
t.Fatalf("registry missing albums controller:\n%s", reg1)
}
if err := refreshRegistry(pluginDir); err != nil {
t.Fatal(err)
}
reg2, err := os.ReadFile(filepath.Join(pluginDir, "registry.gen.go"))
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(reg1, reg2) {
t.Fatal("repeated registry generation changed bytes")
}
if _, err := MakeAdminController(ctx, dir, "golem15.demo", "Albums"); err == nil {
t.Fatal("duplicate controller want error")
}
reg3, err := os.ReadFile(filepath.Join(pluginDir, "registry.gen.go"))
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(reg1, reg3) {
t.Fatal("failed duplicate scaffold changed registry.gen.go")
}
pluginAfter, err := os.ReadFile(filepath.Join(pluginDir, "plugin.go"))
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(pluginBefore, pluginAfter) {
t.Fatal("handwritten plugin.go was rewritten")
}
})
}
type scaffoldAlbumsController struct{}
func (scaffoldAlbumsController) ID() string { return "golem15.demo.albums" }
func (scaffoldAlbumsController) ModelName() string { return "Albums" }
func (scaffoldAlbumsController) ConfigDir() string { return "controllers/albums" }
var _ pact.AdminController = scaffoldAlbumsController{}
func assertScaffoldFiles(t *testing.T, pluginDir string) {
t.Helper()
assertWinterPluginShape(t, pluginDir)