package app import ( "context" "encoding/json" "testing" "github.com/gin-gonic/gin" "kra/pkg/module" platformtask "kra/pkg/task" ) func TestCatalogMigrationIDsAreUnique(t *testing.T) { seen := map[string]string{} for _, definition := range Catalog().Definitions { for _, step := range definition.Migrations { if previous, exists := seen[step.ID]; exists { t.Fatalf("migration %q is declared by both %s and %s", step.ID, previous, definition.Name) } seen[step.ID] = definition.Name } } } func TestCatalogIncludesSystemDefinition(t *testing.T) { catalog := Catalog() if len(catalog.Definitions) != 4 { t.Fatalf("definitions = %d, want 4", len(catalog.Definitions)) } if catalog.Definitions[0].Name != "system" || catalog.Definitions[1].Name != "integration" || catalog.Definitions[2].Name != "task" || catalog.Definitions[3].Name != "payment" { t.Fatalf("definition order = [%q, %q, %q, %q], want [system, integration, task, payment]", catalog.Definitions[0].Name, catalog.Definitions[1].Name, catalog.Definitions[2].Name, catalog.Definitions[3].Name) } if got := catalog.MigrationSteps(); len(got) != 8 { t.Fatalf("module migrations = %d, want 8", len(got)) } if surface := catalog.Surface(); len(surface.Menus) != 3 || len(surface.APIs) != 15 { t.Fatalf("admin surface = %d menus/%d APIs, want 3/15", len(surface.Menus), len(surface.APIs)) } if got := catalog.DefaultTimedTasks(); len(got) != 2 { t.Fatalf("default timed tasks = %d, want 2", len(got)) } } func TestTaskRegistryRegistersStaticModuleMethods(t *testing.T) { method := platformtask.Method{ Name: "test.static", Run: func(context.Context, json.RawMessage) error { return nil }, } catalog := module.Catalog{Definitions: []module.Definition{{Tasks: []platformtask.Method{method}}}} registry := TaskRegistry(catalog) if _, ok := registry.Lookup(method.Name); !ok { t.Fatalf("method %q was not registered", method.Name) } } type testRouteRegistrar struct{ called bool } func (registrar *testRouteRegistrar) RegisterRoutes(*gin.RouterGroup, *gin.RouterGroup, *gin.Engine) { registrar.called = true } type testTaskContributor struct{ name string } func (contributor testTaskContributor) RegisterTasks(registry *platformtask.Registry) { registry.Register(platformtask.Method{ Name: contributor.name, Run: func(context.Context, json.RawMessage) error { return nil }, }) } func TestRuntimeAppliesAllContributions(t *testing.T) { registry := platformtask.NewRegistry() route := &testRouteRegistrar{} runtime := Runtime(RuntimeContributions{ Routes: []module.RouteRegistrar{route}, Tasks: []platformtask.Contributor{testTaskContributor{name: "test.runtime"}}, }, registry) if _, ok := registry.Lookup("test.runtime"); !ok { t.Fatal("runtime task contributor was not applied") } runtime.RegisterRoutes(nil, nil, nil) if !route.called { t.Fatal("runtime route contributor was not called") } }