package main import ( "testing" "time" "github.com/tinode/chat/server/store" "github.com/tinode/chat/server/store/types" ) type passwordResetEventStore struct { testHTTPInfrastructureStore delivered []string } func (s *passwordResetEventStore) MarkEventDelivered(_ types.TenantID, eventID string, _ time.Time) error { s.delivered = append(s.delivered, eventID) return nil } func TestDispatchPasswordResetEvent(t *testing.T) { oldInfrastructure := store.HTTPInfrastructure oldHub, oldSessions := globals.hub, globals.sessionStore defer func() { store.HTTPInfrastructure = oldInfrastructure globals.hub, globals.sessionStore = oldHub, oldSessions }() infrastructure := &passwordResetEventStore{} infrastructure.events = []types.BusinessEvent{{ EventID: "password-reset-1", EventType: "security.password_reset", TargetType: "user", Target: "42", Payload: []byte(`{"user_id":42}`), }} store.HTTPInfrastructure = infrastructure globals.hub = &Hub{routeSrv: make(chan *ServerComMessage, 1)} globals.sessionStore = nil dispatchIMBusinessEvents(types.TenantID(1)) if len(infrastructure.delivered) != 1 || infrastructure.delivered[0] != "password-reset-1" { t.Fatalf("password reset event was not marked delivered: %v", infrastructure.delivered) } if len(globals.hub.routeSrv) != 0 { t.Fatal("password reset event was routed as a regular client event") } } func TestDispatchRegistrationInviteUsageEvent(t *testing.T) { oldInfrastructure, oldInvites := store.HTTPInfrastructure, store.RegistrationInvites oldHub := globals.hub defer func() { store.HTTPInfrastructure, store.RegistrationInvites = oldInfrastructure, oldInvites globals.hub = oldHub }() infrastructure := &passwordResetEventStore{} infrastructure.events = []types.BusinessEvent{{ EventID: "invite-use-1", EventType: "registration.invite_used", TargetType: "user", Target: "42", Payload: []byte(`{"invite_code_id":99}`), }} invites := &testRegistrationInviteStore{} store.HTTPInfrastructure = infrastructure store.RegistrationInvites = invites globals.hub = &Hub{routeSrv: make(chan *ServerComMessage, 1)} dispatchIMBusinessEvents(types.TenantID(1)) if invites.syncedCode != 99 { t.Fatalf("invite usage projection code=%d, want 99", invites.syncedCode) } if len(infrastructure.delivered) != 1 || infrastructure.delivered[0] != "invite-use-1" { t.Fatalf("invite usage event was not marked delivered: %v", infrastructure.delivered) } if len(globals.hub.routeSrv) != 0 { t.Fatal("invite usage event was routed as a regular client event") } } func TestDispatchUserBusinessEventToOnlineSession(t *testing.T) { oldInfrastructure := store.HTTPInfrastructure oldHub, oldSessions := globals.hub, globals.sessionStore defer func() { store.HTTPInfrastructure = oldInfrastructure globals.hub, globals.sessionStore = oldHub, oldSessions }() uid := types.ParseUserId("usrv97xq86jw3c") infrastructure := &passwordResetEventStore{} infrastructure.events = []types.BusinessEvent{{ EventID: "friend-request-1", EventType: "friend.request.created", TargetType: "user", Target: uid.UserId(), Payload: []byte(`{"request_id":"frq_1","user_id":"usrSrc"}`), CreatedAt: time.Now().UTC(), }} store.HTTPInfrastructure = infrastructure globals.hub = &Hub{routeSrv: make(chan *ServerComMessage, 1)} globals.sessionStore = NewSessionStore(time.Minute) session := &Session{sid: "s1", proto: WEBSOCK, uid: uid, tenantID: types.TenantID(1), send: make(chan any, 1)} globals.sessionStore.sessCache[session.sid] = session dispatchIMBusinessEvents(types.TenantID(1)) if len(infrastructure.delivered) != 1 || infrastructure.delivered[0] != "friend-request-1" { t.Fatalf("business event was not marked delivered: %v", infrastructure.delivered) } if len(globals.hub.routeSrv) != 0 { t.Fatal("online user event should be delivered directly to session without topic routing") } select { case raw := <-session.send: msg, ok := raw.(*ServerComMessage) if !ok || msg.Info == nil { t.Fatalf("unexpected outbound message: %#v", raw) } if msg.Info.What != "im" || msg.Info.Event != "friend.request.created" || msg.Info.Topic != uid.UserId() { t.Fatalf("unexpected info event: %#v", msg.Info) } default: t.Fatal("online user session did not receive business info event") } }