package main import ( "testing" "time" "github.com/segmentio/kafka-go" "github.com/tinode/chat/server/store" "github.com/tinode/chat/server/store/types" ) func TestKafkaTopicsIncludeExternalWorkbenchEvent(t *testing.T) { topics := kafkaTopics(nil) if topics["workbench_external"] != "im.workbench.event" { t.Fatalf("unexpected workbench external topic: %q", topics["workbench_external"]) } if _, ok := topics["workbench_event"]; ok { t.Fatal("legacy in-process workbench_event topic key must not be configured") } } func TestDecodeKafkaWorkbenchEventDirectPayload(t *testing.T) { msg := kafka.Message{Value: []byte(`{ "event_id":"wbe_1", "trace_id":"trace-1", "tenant_id":7, "tenant_code":"default", "actor_user_id":42, "module":"meeting", "action":"meeting.created", "resource_id":"meeting-1", "target_user_ids":[42,43], "title":"会议通知", "summary":"周会", "occurred_at":"2026-09-13T10:00:00Z", "data":{"meeting_id":"meeting-1"} }`)} payload, envelope, err := decodeKafkaWorkbenchEvent(kafkaEnvelope{}, msg) if err != nil { t.Fatalf("decodeKafkaWorkbenchEvent returned error: %v", err) } if payload.EventID != "wbe_1" || payload.ActorUserID != 42 || len(payload.TargetUserIDs) != 2 { t.Fatalf("unexpected payload: %#v", payload) } if envelope.EventID != "wbe_1" || envelope.EventType != "workbench.meeting.created" || envelope.BizType != "meeting" || envelope.BizID != "meeting-1" { t.Fatalf("unexpected normalized envelope: %#v", envelope) } if envelope.Actor == nil || envelope.Actor.ID != types.Uid(42).UserId() { t.Fatalf("unexpected actor: %#v", envelope.Actor) } if envelope.OccurredAt.IsZero() || envelope.TenantID != types.TenantID(7) { t.Fatalf("unexpected occurrence or tenant: %#v", envelope) } } func TestExecuteKafkaExternalWorkbenchEventCreatesNotificationForNonActor(t *testing.T) { oldSecurity := store.Security defer func() { store.Security = oldSecurity }() security := &testSecurityStore{} store.Security = security payload := kafkaExternalWorkbenchEvent{ EventID: "wbe_1", TenantID: 7, ActorUserID: 42, Module: "meeting", Action: "meeting.created", ResourceID: "meeting-1", TargetUserIDs: []int64{42, 43}, Title: "会议通知", Summary: "周会", OccurredAt: time.Date(2026, 9, 13, 10, 0, 0, 0, time.UTC), Data: map[string]any{"meeting_id": "meeting-1"}, } envelope := kafkaEnvelope{EventID: payload.EventID} if err := executeKafkaExternalWorkbenchEvent(7, envelope, payload); err != nil { t.Fatalf("executeKafkaExternalWorkbenchEvent returned error: %v", err) } if len(security.notifications) != 1 { t.Fatalf("expected one notification for non-actor target, got %#v", security.notifications) } if security.notifications[0].UserID != types.Uid(43) || security.notifications[0].EventType != "meeting.created" { t.Fatalf("unexpected notification: %#v", security.notifications[0]) } }