registry_test.go raw

   1  package specialkinds
   2  
   3  import (
   4  	"context"
   5  	"errors"
   6  	"testing"
   7  
   8  	"next.orly.dev/pkg/nostr/encoders/event"
   9  )
  10  
  11  func TestNewRegistry(t *testing.T) {
  12  	r := NewRegistry()
  13  	if r == nil {
  14  		t.Fatal("NewRegistry returned nil")
  15  	}
  16  	if r.HandlerCount() != 0 {
  17  		t.Errorf("expected 0 handlers, got %d", r.HandlerCount())
  18  	}
  19  }
  20  
  21  func TestRegistryRegister(t *testing.T) {
  22  	r := NewRegistry()
  23  
  24  	h := NewHandlerFunc(
  25  		"test-handler",
  26  		func(ev *event.E) bool { return true },
  27  		func(ctx context.Context, ev *event.E, hctx *HandlerContext) Result {
  28  			return Handled("test")
  29  		},
  30  	)
  31  
  32  	r.Register(h)
  33  
  34  	if r.HandlerCount() != 1 {
  35  		t.Errorf("expected 1 handler, got %d", r.HandlerCount())
  36  	}
  37  
  38  	names := r.ListHandlers()
  39  	if len(names) != 1 || names[0] != "test-handler" {
  40  		t.Errorf("unexpected handler names: %v", names)
  41  	}
  42  }
  43  
  44  func TestRegistryTryHandle_NoMatch(t *testing.T) {
  45  	r := NewRegistry()
  46  
  47  	// Register a handler that never matches
  48  	h := NewHandlerFunc(
  49  		"never-matches",
  50  		func(ev *event.E) bool { return false },
  51  		func(ctx context.Context, ev *event.E, hctx *HandlerContext) Result {
  52  			return Handled("should not be called")
  53  		},
  54  	)
  55  	r.Register(h)
  56  
  57  	ev := &event.E{Kind: 1}
  58  	result, matched := r.TryHandle(context.Background(), ev, nil)
  59  
  60  	if matched {
  61  		t.Error("expected no match, got matched")
  62  	}
  63  	if result != nil {
  64  		t.Error("expected nil result when no match")
  65  	}
  66  }
  67  
  68  func TestRegistryTryHandle_Match(t *testing.T) {
  69  	r := NewRegistry()
  70  
  71  	// Register a handler that matches kind 1
  72  	h := NewHandlerFunc(
  73  		"kind-1-handler",
  74  		func(ev *event.E) bool { return ev.Kind == 1 },
  75  		func(ctx context.Context, ev *event.E, hctx *HandlerContext) Result {
  76  			return Handled("processed kind 1")
  77  		},
  78  	)
  79  	r.Register(h)
  80  
  81  	ev := &event.E{Kind: 1}
  82  	result, matched := r.TryHandle(context.Background(), ev, nil)
  83  
  84  	if !matched {
  85  		t.Error("expected match, got no match")
  86  	}
  87  	if result == nil {
  88  		t.Fatal("expected result, got nil")
  89  	}
  90  	if !result.Handled {
  91  		t.Error("expected Handled=true")
  92  	}
  93  	if result.Message != "processed kind 1" {
  94  		t.Errorf("unexpected message: %s", result.Message)
  95  	}
  96  }
  97  
  98  func TestRegistryTryHandle_FirstMatchWins(t *testing.T) {
  99  	r := NewRegistry()
 100  
 101  	// Register two handlers that both match kind 1
 102  	h1 := NewHandlerFunc(
 103  		"first-handler",
 104  		func(ev *event.E) bool { return ev.Kind == 1 },
 105  		func(ctx context.Context, ev *event.E, hctx *HandlerContext) Result {
 106  			return Handled("first")
 107  		},
 108  	)
 109  	h2 := NewHandlerFunc(
 110  		"second-handler",
 111  		func(ev *event.E) bool { return ev.Kind == 1 },
 112  		func(ctx context.Context, ev *event.E, hctx *HandlerContext) Result {
 113  			return Handled("second")
 114  		},
 115  	)
 116  	r.Register(h1)
 117  	r.Register(h2)
 118  
 119  	ev := &event.E{Kind: 1}
 120  	result, _ := r.TryHandle(context.Background(), ev, nil)
 121  
 122  	if result.Message != "first" {
 123  		t.Errorf("expected first handler to win, got message: %s", result.Message)
 124  	}
 125  }
 126  
 127  func TestHandlerContext(t *testing.T) {
 128  	r := NewRegistry()
 129  
 130  	var capturedCtx *HandlerContext
 131  
 132  	h := NewHandlerFunc(
 133  		"context-capture",
 134  		func(ev *event.E) bool { return true },
 135  		func(ctx context.Context, ev *event.E, hctx *HandlerContext) Result {
 136  			capturedCtx = hctx
 137  			return Handled("captured")
 138  		},
 139  	)
 140  	r.Register(h)
 141  
 142  	hctx := &HandlerContext{
 143  		AuthedPubkey: []byte{1, 2, 3},
 144  		Remote:       "127.0.0.1:12345",
 145  		ConnectionID: "conn-abc",
 146  	}
 147  
 148  	r.TryHandle(context.Background(), &event.E{Kind: 1}, hctx)
 149  
 150  	if capturedCtx == nil {
 151  		t.Fatal("handler context not captured")
 152  	}
 153  	if string(capturedCtx.AuthedPubkey) != string(hctx.AuthedPubkey) {
 154  		t.Error("AuthedPubkey mismatch")
 155  	}
 156  	if capturedCtx.Remote != hctx.Remote {
 157  		t.Error("Remote mismatch")
 158  	}
 159  	if capturedCtx.ConnectionID != hctx.ConnectionID {
 160  		t.Error("ConnectionID mismatch")
 161  	}
 162  }
 163  
 164  func TestResultConstructors(t *testing.T) {
 165  	t.Run("Handled", func(t *testing.T) {
 166  		r := Handled("msg")
 167  		if !r.Handled || r.Continue || r.SaveEvent || r.Error != nil {
 168  			t.Error("unexpected Handled result")
 169  		}
 170  		if r.Message != "msg" {
 171  			t.Errorf("unexpected message: %s", r.Message)
 172  		}
 173  	})
 174  
 175  	t.Run("HandledWithSave", func(t *testing.T) {
 176  		r := HandledWithSave("msg")
 177  		if !r.Handled || r.Continue || !r.SaveEvent || r.Error != nil {
 178  			t.Error("unexpected HandledWithSave result")
 179  		}
 180  	})
 181  
 182  	t.Run("ContinueProcessing", func(t *testing.T) {
 183  		r := ContinueProcessing()
 184  		if r.Handled || !r.Continue || r.SaveEvent || r.Error != nil {
 185  			t.Error("unexpected ContinueProcessing result")
 186  		}
 187  	})
 188  
 189  	t.Run("ErrorResult", func(t *testing.T) {
 190  		err := errors.New("test error")
 191  		r := ErrorResult(err)
 192  		if r.Handled || r.Continue || r.SaveEvent || r.Error != err {
 193  			t.Error("unexpected ErrorResult result")
 194  		}
 195  	})
 196  }
 197  
 198  func TestHandlerFuncInterface(t *testing.T) {
 199  	h := NewHandlerFunc(
 200  		"test",
 201  		func(ev *event.E) bool { return ev.Kind == 42 },
 202  		func(ctx context.Context, ev *event.E, hctx *HandlerContext) Result {
 203  			return Handled("42")
 204  		},
 205  	)
 206  
 207  	// Check interface compliance
 208  	var _ Handler = h
 209  
 210  	if h.Name() != "test" {
 211  		t.Errorf("unexpected name: %s", h.Name())
 212  	}
 213  
 214  	if !h.CanHandle(&event.E{Kind: 42}) {
 215  		t.Error("expected CanHandle to return true for kind 42")
 216  	}
 217  	if h.CanHandle(&event.E{Kind: 1}) {
 218  		t.Error("expected CanHandle to return false for kind 1")
 219  	}
 220  
 221  	result := h.Handle(context.Background(), &event.E{Kind: 42}, nil)
 222  	if result.Message != "42" {
 223  		t.Errorf("unexpected result message: %s", result.Message)
 224  	}
 225  }
 226