feat(surf): print the serve URL and admin status on startup
- Add surf.Router.AdminPrefix (additive): the admin mount path and true when BuildRouter mounted the cabana admin, false otherwise - serve binds with net.Listen before printing, so a busy port fails without a misleading URL, then prints the listen address with a browser URL and an admin status line: the admin URL, a warning naming summer admin:create when backend_users is empty or missing, or admin: off with the steps to add an admin controller - The administrator count is bounded by a 2 s timeout and never fails boot - route:list ends with the same admin status line - surf and cabana READMEs and the console and routing docs describe the output
This commit is contained in:
@@ -1,12 +1,15 @@
|
||||
package surf
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"git.golem15.com/golem15/summercms/modules/backpack"
|
||||
"git.golem15.com/golem15/summercms/modules/bonfire"
|
||||
"git.golem15.com/golem15/summercms/modules/compass"
|
||||
"gocloud.dev/blob"
|
||||
)
|
||||
@@ -51,3 +54,71 @@ func serveTestApp(t *testing.T, storageYAML string) *backpack.App {
|
||||
}
|
||||
return backpack.New(cfg)
|
||||
}
|
||||
|
||||
func TestServeURL(t *testing.T) {
|
||||
for _, tc := range []struct{ addr, want string }{
|
||||
{":8123", "http://127.0.0.1:8123/"},
|
||||
{"127.0.0.1:9000", "http://127.0.0.1:9000/"},
|
||||
{"[::1]:8080", "http://[::1]:8080/"},
|
||||
{"0.0.0.0:80", "http://127.0.0.1/"},
|
||||
{"[::]:8080", "http://127.0.0.1:8080/"},
|
||||
{"localhost:3000", "http://localhost:3000/"},
|
||||
{"8080", ""},
|
||||
{"", ""},
|
||||
{"127.0.0.1:", ""},
|
||||
} {
|
||||
if got := serveURL(tc.addr); got != tc.want {
|
||||
t.Errorf("serveURL(%q) = %q, want %q", tc.addr, got, tc.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestServeBanner(t *testing.T) {
|
||||
listen := bannerLine{text: "listening on :8123, open http://127.0.0.1:8123/"}
|
||||
mounted := bannerLine{text: "admin: http://127.0.0.1:8123/backend"}
|
||||
create := "summer admin:create --email you@example.com --superuser"
|
||||
for _, tc := range []struct {
|
||||
name string
|
||||
addr string
|
||||
prefix string
|
||||
mounted bool
|
||||
admins adminPresence
|
||||
want []bannerLine
|
||||
}{
|
||||
{"present", ":8123", "/backend", true, adminsPresent, []bannerLine{listen, mounted}},
|
||||
{"none", ":8123", "/backend", true, adminsNone, []bannerLine{listen, mounted,
|
||||
{warn: true, text: "no administrators yet; create one with " + create}}},
|
||||
{"missing table", ":8123", "/backend", true, adminsMissingTable, []bannerLine{listen, mounted,
|
||||
{warn: true, text: "the admin tables do not exist yet; run summer migrate, then " + create}}},
|
||||
{"unknown", ":8123", "/backend", true, adminsUnknown, []bannerLine{listen, mounted,
|
||||
{text: "sign in with an administrator; " + create + " creates one"}}},
|
||||
{"off", ":8123", "", false, adminsUnknown, []bannerLine{listen,
|
||||
{text: "admin: off — no plugin registers an admin controller"},
|
||||
{text: "to add one, run summer make:admin-controller <vendor.plugin> <Name>, then summer build, summer migrate and " + create + "; the admin needs SUMMER_ADMIN__JWT__SECRET, which summer new writes to .env"}}},
|
||||
{"unparsable address", "8080", "/backend", true, adminsPresent, []bannerLine{
|
||||
{text: "listening on 8080"}, {text: "admin: mounted at /backend"}}},
|
||||
} {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
got := serveBanner(tc.addr, tc.prefix, tc.mounted, tc.admins)
|
||||
if !slices.Equal(got, tc.want) {
|
||||
t.Fatalf("serveBanner:\n got %#v\nwant %#v", got, tc.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestPrintBanner(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
out := bonfire.NewOutput(strings.NewReader(""), &buf, &buf)
|
||||
printBanner(out, []bannerLine{{text: "plain"}, {warn: true, text: "careful"}})
|
||||
got := buf.String()
|
||||
if !strings.Contains(got, "ℹ plain") || !strings.Contains(got, "⚠ careful") {
|
||||
t.Fatalf("printBanner output = %q", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCountAdminsNilDB(t *testing.T) {
|
||||
if got := countAdmins(t.Context(), nil); got != adminsUnknown {
|
||||
t.Fatalf("countAdmins(nil) = %v, want adminsUnknown", got)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user