- Build-time discovery (D-028, the Caddy pattern): a module self-registers from init(); internal/modules/imports_gen.go (go:generate) blank-imports every module directory, so THE DIRECTORY IS THE SOURCE OF TRUTH - The registry: deterministic registration order, config-backed enable/disable (D-038), required modules, name-prefixed migrations, Mount() into the door - The name-collision guard now also fails a module named for a reserved level-1 workflow (SPEC-009 §13 Q-1) — access · static · api · media · ws · dev — derived from routing.ReservedWorkflows, `home` excepted (D-2) - home: the reference dashboard module, and the core Modules page
62 lines
2.1 KiB
Go
62 lines
2.1 KiB
Go
package modules
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"git.lohmar.co.uk/cclohmar/NextMyDay/internal/core/module"
|
|
"git.lohmar.co.uk/cclohmar/NextMyDay/internal/core/routing"
|
|
"git.lohmar.co.uk/cclohmar/NextMyDay/internal/core/server"
|
|
)
|
|
|
|
// fakeResolver answers the pure model's GUID question.
|
|
type fakeResolver map[string]bool // guid -> enrolled
|
|
|
|
func (f fakeResolver) GUID(guid string) (bool, bool) {
|
|
enrolled, found := f[guid]
|
|
return found, enrolled
|
|
}
|
|
|
|
// TestDiscoveryFindsHome proves the generated aggregator wires the `home`
|
|
// directory into the registry — build-time discovery, no core edits (AC-1).
|
|
func TestDiscoveryFindsHome(t *testing.T) {
|
|
var found bool
|
|
for _, m := range module.Discovered() {
|
|
if m.Name() == "home" {
|
|
found = true
|
|
}
|
|
}
|
|
if !found {
|
|
t.Fatalf("the `home` module was not discovered: %v", module.Discovered())
|
|
}
|
|
}
|
|
|
|
// TestDoorDispatchesToDiscoveredHome is the end-to-end proof (definition of
|
|
// done): the discovered registry mounts into the door's registry, and the pure
|
|
// model resolves /{GUID} and /{GUID}/home to the home module's dashboard.
|
|
func TestDoorDispatchesToDiscoveredHome(t *testing.T) {
|
|
reg, err := module.Load(nil)
|
|
if err != nil {
|
|
t.Fatalf("module.Load: %v", err)
|
|
}
|
|
dst := server.NewMapRegistry()
|
|
reg.Mount(dst)
|
|
|
|
res := fakeResolver{"guid-1": true}
|
|
|
|
// /{GUID} → the home module's DEFAULT route.
|
|
root := routing.Dispatch(res, dst, "/guid-1", "", "")
|
|
if root.Kind != routing.KindRoute || root.Module != "home" || root.Function != "dashboard" {
|
|
t.Errorf("/{GUID} = %+v, want module home function dashboard (AC-1)", root)
|
|
}
|
|
// /{GUID}/home → `home` is the PARAM2 case at level 2 (SPEC-002 §4.4); with
|
|
// PARAM3 absent it reaches the home module's default too.
|
|
home := routing.Dispatch(res, dst, "/guid-1/home", "", "")
|
|
if home.Kind != routing.KindRoute || home.Module != "home" || home.Function != "dashboard" {
|
|
t.Errorf("/{GUID}/home = %+v, want module home function dashboard (AC-1)", home)
|
|
}
|
|
// An unknown module still 404s.
|
|
bad := routing.Dispatch(res, dst, "/guid-1/nope/x", "", "")
|
|
if bad.Kind != routing.KindNotFound {
|
|
t.Errorf("/{GUID}/nope/x = %+v, want NotFound", bad)
|
|
}
|
|
}
|