package restheadspec import ( "context" "fmt" "testing" ) // TestHookRegistry tests the hook registry functionality func TestHookRegistry(t *testing.T) { registry := NewHookRegistry() // Test registering a hook called := false hook := func(ctx *HookContext) error { called = true return nil } registry.Register(BeforeRead, hook) if registry.Count(BeforeRead) != 1 { t.Errorf("Expected 1 hook, got %d", registry.Count(BeforeRead)) } // Test executing a hook ctx := &HookContext{ Context: context.Background(), Schema: "test", Entity: "users", } err := registry.Execute(BeforeRead, ctx) if err != nil { t.Errorf("Hook execution failed: %v", err) } if !called { t.Error("Hook was not called") } } // TestHookExecution tests hook execution order func TestHookExecutionOrder(t *testing.T) { registry := NewHookRegistry() order := []int{} hook1 := func(ctx *HookContext) error { order = append(order, 1) return nil } hook2 := func(ctx *HookContext) error { order = append(order, 2) return nil } hook3 := func(ctx *HookContext) error { order = append(order, 3) return nil } registry.Register(BeforeCreate, hook1) registry.Register(BeforeCreate, hook2) registry.Register(BeforeCreate, hook3) ctx := &HookContext{ Context: context.Background(), Schema: "test", Entity: "users", } err := registry.Execute(BeforeCreate, ctx) if err != nil { t.Errorf("Hook execution failed: %v", err) } if len(order) != 3 { t.Errorf("Expected 3 hooks to be called, got %d", len(order)) } if order[0] != 1 || order[1] != 2 || order[2] != 3 { t.Errorf("Hooks executed in wrong order: %v", order) } } // TestHookError tests hook error handling func TestHookError(t *testing.T) { registry := NewHookRegistry() executed := []string{} hook1 := func(ctx *HookContext) error { executed = append(executed, "hook1") return nil } hook2 := func(ctx *HookContext) error { executed = append(executed, "hook2") return fmt.Errorf("hook2 error") } hook3 := func(ctx *HookContext) error { executed = append(executed, "hook3") return nil } registry.Register(BeforeUpdate, hook1) registry.Register(BeforeUpdate, hook2) registry.Register(BeforeUpdate, hook3) ctx := &HookContext{ Context: context.Background(), Schema: "test", Entity: "users", } err := registry.Execute(BeforeUpdate, ctx) if err == nil { t.Error("Expected error from hook execution") } if len(executed) != 2 { t.Errorf("Expected only 2 hooks to be executed, got %d", len(executed)) } if executed[0] != "hook1" || executed[1] != "hook2" { t.Errorf("Unexpected execution order: %v", executed) } } // TestHookDataModification tests modifying data in hooks func TestHookDataModification(t *testing.T) { registry := NewHookRegistry() modifyHook := func(ctx *HookContext) error { if dataMap, ok := ctx.Data.(map[string]interface{}); ok { dataMap["modified"] = true ctx.Data = dataMap } return nil } registry.Register(BeforeCreate, modifyHook) data := map[string]interface{}{ "name": "test", } ctx := &HookContext{ Context: context.Background(), Schema: "test", Entity: "users", Data: data, } err := registry.Execute(BeforeCreate, ctx) if err != nil { t.Errorf("Hook execution failed: %v", err) } modifiedData := ctx.Data.(map[string]interface{}) if !modifiedData["modified"].(bool) { t.Error("Data was not modified by hook") } } // TestRegisterMultiple tests registering a hook for multiple types func TestRegisterMultiple(t *testing.T) { registry := NewHookRegistry() called := 0 hook := func(ctx *HookContext) error { called++ return nil } registry.RegisterMultiple([]HookType{ BeforeRead, BeforeCreate, BeforeUpdate, }, hook) if registry.Count(BeforeRead) != 1 { t.Error("Hook not registered for BeforeRead") } if registry.Count(BeforeCreate) != 1 { t.Error("Hook not registered for BeforeCreate") } if registry.Count(BeforeUpdate) != 1 { t.Error("Hook not registered for BeforeUpdate") } ctx := &HookContext{ Context: context.Background(), Schema: "test", Entity: "users", } registry.Execute(BeforeRead, ctx) registry.Execute(BeforeCreate, ctx) registry.Execute(BeforeUpdate, ctx) if called != 3 { t.Errorf("Expected hook to be called 3 times, got %d", called) } } // TestClearHooks tests clearing hooks func TestClearHooks(t *testing.T) { registry := NewHookRegistry() hook := func(ctx *HookContext) error { return nil } registry.Register(BeforeRead, hook) registry.Register(BeforeCreate, hook) if registry.Count(BeforeRead) != 1 { t.Error("Hook not registered") } registry.Clear(BeforeRead) if registry.Count(BeforeRead) != 0 { t.Error("Hook not cleared") } if registry.Count(BeforeCreate) != 1 { t.Error("Wrong hook was cleared") } } // TestClearAllHooks tests clearing all hooks func TestClearAllHooks(t *testing.T) { registry := NewHookRegistry() hook := func(ctx *HookContext) error { return nil } registry.Register(BeforeRead, hook) registry.Register(BeforeCreate, hook) registry.Register(BeforeUpdate, hook) registry.ClearAll() if registry.Count(BeforeRead) != 0 || registry.Count(BeforeCreate) != 0 || registry.Count(BeforeUpdate) != 0 { t.Error("Not all hooks were cleared") } } // TestHasHooks tests checking if hooks exist func TestHasHooks(t *testing.T) { registry := NewHookRegistry() if registry.HasHooks(BeforeRead) { t.Error("Should not have hooks initially") } hook := func(ctx *HookContext) error { return nil } registry.Register(BeforeRead, hook) if !registry.HasHooks(BeforeRead) { t.Error("Should have hooks after registration") } } // TestGetAllHookTypes tests getting all registered hook types func TestGetAllHookTypes(t *testing.T) { registry := NewHookRegistry() hook := func(ctx *HookContext) error { return nil } registry.Register(BeforeRead, hook) registry.Register(BeforeCreate, hook) registry.Register(AfterUpdate, hook) types := registry.GetAllHookTypes() if len(types) != 3 { t.Errorf("Expected 3 hook types, got %d", len(types)) } // Verify all expected types are present expectedTypes := map[HookType]bool{ BeforeRead: true, BeforeCreate: true, AfterUpdate: true, } for _, hookType := range types { if !expectedTypes[hookType] { t.Errorf("Unexpected hook type: %s", hookType) } } } // TestHookContextHandler tests that hooks can access the handler func TestHookContextHandler(t *testing.T) { registry := NewHookRegistry() var capturedHandler *Handler hook := func(ctx *HookContext) error { // Verify that the handler is accessible from the context if ctx.Handler == nil { return fmt.Errorf("handler is nil in hook context") } capturedHandler = ctx.Handler return nil } registry.Register(BeforeRead, hook) // Create a mock handler handler := &Handler{ hooks: registry, } ctx := &HookContext{ Context: context.Background(), Handler: handler, Schema: "test", Entity: "users", } err := registry.Execute(BeforeRead, ctx) if err != nil { t.Errorf("Hook execution failed: %v", err) } if capturedHandler == nil { t.Error("Handler was not captured from hook context") } if capturedHandler != handler { t.Error("Captured handler does not match original handler") } }