Files
summercms/docs/examples/blog/blog_test.go
Jakub Zych 41a3190956 feat(11.1-05): add the acme.blog walkthrough plugin with its model, migration and posts route
- docs/examples/blog: scaffolder output for acme.blog (make:plugin, make:model)
  in the root module, with a Post model, a fill allow-list and NewPost, the
  create migration and GET /api/blog/posts paginated through lagoon
- short tests activate the plugin, check the route with surf, the fill
  allow-list and the migration order
- docs/setup/porting-a-plugin.md: registration, model, migrations and routes
  sections with src= copies of the plugin
- TestDocsRequiredPages requires setup/porting-a-plugin
2026-09-30 23:28:41 +02:00

98 lines
2.9 KiB
Go

package blog_test
import (
"os"
"path/filepath"
"slices"
"testing"
"git.golem15.com/golem15/summercms/docs/examples/blog"
"git.golem15.com/golem15/summercms/docs/examples/blog/models"
"git.golem15.com/golem15/summercms/modules/backpack"
"git.golem15.com/golem15/summercms/modules/compass"
"git.golem15.com/golem15/summercms/modules/pact"
"git.golem15.com/golem15/summercms/modules/party"
"git.golem15.com/golem15/summercms/modules/surf"
)
// activate boots acme.blog the way the generated main does: an application
// config directory with the required HTTP limits, then party.Activate with
// the plugin ID.
func activate(t *testing.T) (*backpack.App, party.Plugin) {
t.Helper()
dir := t.TempDir()
httpYAML := "body_limits:\n default_bytes: 1048576\n upload_bytes: 10485760\n"
if err := os.WriteFile(filepath.Join(dir, "http.yaml"), []byte(httpYAML), 0o644); err != nil {
t.Fatal(err)
}
cfg, err := compass.Open(compass.Options{Dir: dir, Env: "testing", Environ: []string{}})
if err != nil {
t.Fatal(err)
}
app := backpack.New(cfg)
plugins, err := party.Activate(app, []string{"acme.blog"})
if err != nil {
t.Fatalf("Activate: %v", err)
}
if len(plugins) != 1 {
t.Fatalf("Activate returned %d plugins, want 1", len(plugins))
}
return app, plugins[0]
}
func TestPluginActivates(t *testing.T) {
app, p := activate(t)
if p.ID() != "acme.blog" {
t.Fatalf("ID = %q, want acme.blog", p.ID())
}
if _, ok := p.(*blog.Plugin); !ok {
t.Fatalf("activated plugin is %T, want *blog.Plugin", p)
}
if len(p.Requires()) != 0 {
t.Errorf("Requires = %v, want none", p.Requires())
}
if _, ok := p.(pact.HasRoutes); !ok {
t.Error("plugin does not implement pact.HasRoutes")
}
if _, ok := p.(pact.HasConfig); !ok {
t.Error("plugin does not implement pact.HasConfig")
}
if _, ok := p.(pact.HasLang); !ok {
t.Error("plugin does not implement pact.HasLang")
}
hasModels, ok := p.(pact.HasModels)
if !ok {
t.Fatal("plugin does not implement pact.HasModels")
}
if got := hasModels.Models(); len(got) != 1 {
t.Errorf("Models = %v, want one model", got)
} else if _, ok := got[0].(*models.Post); !ok {
t.Errorf("Models()[0] is %T, want *models.Post", got[0])
}
hasMigrations, ok := p.(pact.HasMigrations)
if !ok {
t.Fatal("plugin does not implement pact.HasMigrations")
}
if len(hasMigrations.Migrations()) == 0 {
t.Error("Migrations is empty")
}
if got := app.Config.Int("acme.blog.per_page"); got != 15 {
t.Errorf("acme.blog.per_page = %d, want the plugin default 15", got)
}
}
func TestRoutesRegistered(t *testing.T) {
app, p := activate(t)
router, err := surf.BuildRouter(app, []party.Plugin{p})
if err != nil {
t.Fatalf("BuildRouter: %v", err)
}
routes := router.Routes()
found := slices.ContainsFunc(routes, func(r surf.RouteInfo) bool {
return r.Method == "GET" && r.Pattern == "/api/blog/posts" && r.PluginID == "acme.blog"
})
if !found {
t.Fatalf("GET /api/blog/posts is not registered for acme.blog: %+v", routes)
}
}