| 151 | } |
| 152 | |
| 153 | func TestHandleMessageErrors(t *testing.T) { |
| 154 | r := NewRouter() |
| 155 | Register(r, func(_ context.Context, _ string, _ TestEventV1) error { return nil }) |
| 156 | |
| 157 | tests := []struct { |
| 158 | name string |
| 159 | input []byte |
| 160 | errorContains string |
| 161 | }{ |
| 162 | { |
| 163 | name: "invalid json", |
| 164 | input: []byte(`{ "kind": "TestEvent", "apiVe`), |
| 165 | errorContains: "invalid envelope", |
| 166 | }, |
| 167 | { |
| 168 | name: "unknown handler", |
| 169 | input: mustNew(TestEventV2{ID: "id", Priority: 0}), |
| 170 | errorContains: "no handler registered", |
| 171 | }, |
| 172 | { |
| 173 | name: "schema mismatch (payload data invalid)", |
| 174 | // Correct envelope, but 'data' is an array instead of expected object |
| 175 | input: []byte(`{"kind": "TestEvent", "apiVersion": "v1", "data": []}`), |
| 176 | errorContains: "parsing event.TestEventV1 failed", |
| 177 | }, |
| 178 | } |
| 179 | |
| 180 | for _, tc := range tests { |
| 181 | t.Run(tc.name, func(t *testing.T) { |
| 182 | err := r.HandleMessage(t.Context(), "id", tc.input) |
| 183 | |
| 184 | if err == nil { |
| 185 | t.Fatal("expected error, got nil") |
| 186 | } |
| 187 | |
| 188 | // All errors from router should be Permanent errors (ErrUnprocessableEntity) |
| 189 | if !errors.Is(err, ErrUnprocessableEntity) { |
| 190 | t.Errorf("expected error to wrap ErrUnprocessableEntity, got: %v", err) |
| 191 | } |
| 192 | |
| 193 | if tc.errorContains != "" && !strings.Contains(err.Error(), tc.errorContains) { |
| 194 | t.Errorf("expected error containing %q, got %q", tc.errorContains, err.Error()) |
| 195 | } |
| 196 | }) |
| 197 | } |
| 198 | } |
| 199 | |
| 200 | // Helper to ignore errors in test table setup. |
| 201 | func mustNew[T Event](e T) []byte { |