package push_test import ( "testing" "scrabble/gateway/internal/push" ) func TestHubRoutesByUser(t *testing.T) { h := push.NewHub(4) chA, cancelA := h.Subscribe("user-a") defer cancelA() chB, cancelB := h.Subscribe("user-b") defer cancelB() h.Publish(push.Event{UserID: "user-a", Kind: "your_turn"}) select { case e := <-chA: if e.Kind != "your_turn" { t.Fatalf("user-a received %q", e.Kind) } default: t.Fatal("user-a should have received the event") } select { case <-chB: t.Fatal("user-b must not receive user-a's event") default: } } func TestHubDropsOnOverflow(t *testing.T) { h := push.NewHub(1) ch, cancel := h.Subscribe("u") defer cancel() for i := 0; i < 5; i++ { h.Publish(push.Event{UserID: "u", Kind: "chat_message"}) } if got := len(ch); got != 1 { t.Fatalf("buffered %d events, want 1 (overflow dropped)", got) } } func TestHubUnsubscribeClosesChannel(t *testing.T) { h := push.NewHub(2) ch, cancel := h.Subscribe("u") cancel() if _, ok := <-ch; ok { t.Fatal("channel should be closed after unsubscribe") } if h.SubscriberCount() != 0 { t.Fatalf("subscriber count = %d, want 0", h.SubscriberCount()) } h.Publish(push.Event{UserID: "u"}) // must not panic } func TestHubHasSubscribers(t *testing.T) { h := push.NewHub(2) if h.HasSubscribers("u") { t.Fatal("no subscribers yet") } _, cancel := h.Subscribe("u") if !h.HasSubscribers("u") { t.Error("u should be reported online after Subscribe") } if h.HasSubscribers("other") { t.Error("other has no subscription") } cancel() if h.HasSubscribers("u") { t.Error("u should be offline after unsubscribe") } }