Files

102 lines
4.1 KiB
Go

package api
import (
"context"
"errors"
"net/http"
"net/http/httptest"
"testing"
"time"
"git.ipao.vip/rogee/creator-hub/internal/creator"
hub "git.ipao.vip/rogee/creator-hub/internal/environment"
)
func TestCreatorEventFromGatewayNoticeValidatesAndNormalizesInput(t *testing.T) {
input, err := creatorEventFromGatewayNotice("account-1", creatorGatewayEventNotice{
EventKey: "1",
EventType: "dm",
InteractorUID: "123",
MessageText: " hello ",
PlatformEventAt: "2026-09-17T08:00:00+08:00",
GatewayReceivedAt: "2026-09-17T00:00:01Z",
})
if err != nil {
t.Fatal(err)
}
if input.MessageType != creator.MessageTypeText || input.MessageText != "hello" || input.PlatformEventAt == nil || input.GatewayReceivedAt == nil {
t.Fatalf("normalized event = %#v", input)
}
if !input.PlatformEventAt.Equal(time.Date(2026, 9, 17, 0, 0, 0, 0, time.UTC)) {
t.Fatalf("platform event time = %v", input.PlatformEventAt)
}
invalid := []creatorGatewayEventNotice{
{EventKey: "", EventType: "comment"},
{EventKey: "1", EventType: "unknown"},
{EventKey: "1", EventType: "comment", InteractorUID: "0"},
{EventKey: "1", EventType: "comment", CommentID: "bad"},
{EventKey: "1", EventType: "comment", MessageType: "bad"},
{EventKey: "1", EventType: "comment", PlatformEventAt: "bad"},
{EventKey: "1", EventType: "comment", GatewayReceivedAt: "bad"},
}
for index, notice := range invalid {
if _, err := creatorEventFromGatewayNotice("account-1", notice); err == nil {
t.Errorf("invalid notice %d returned no error", index)
}
}
if _, err := creatorEventFromGatewayNotice("", creatorGatewayEventNotice{EventKey: "1", EventType: "comment"}); !errors.Is(err, creator.ErrInvalid) {
t.Fatalf("empty account error = %v", err)
}
}
func TestCreatorEventListenerControlPathsRemainVisible(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
cancel()
if waitCreatorEventBackoff(ctx, time.Millisecond) {
t.Fatal("canceled listener backoff was reported as ready")
}
if !waitCreatorEventBackoff(context.Background(), 0) {
t.Fatal("zero listener backoff was not ready")
}
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method == http.MethodDelete {
w.WriteHeader(http.StatusNoContent)
return
}
w.WriteHeader(http.StatusBadGateway)
}))
stopCreatorEventListener("account-1", hub.Gateway{Endpoint: server.URL}, "/v1/events", map[string]any{})
server.Close()
server = httptest.NewServer(http.NotFoundHandler())
stopCreatorEventListener("account-1", hub.Gateway{Endpoint: server.URL}, "/v1/events", map[string]any{})
server.Close()
binding := creatorEventBinding{accountID: "account-1", env: testRunnableEnvironment()}
runCreatorEventListener(context.Background(), nil, binding, nil, nil)
manager := &creatorEventListenerManager{items: map[string]creatorEventListenerHandle{}}
if err := manager.reconcile(context.Background(), nil, nil, nil, nil, nil); !errors.Is(err, creator.ErrUnavailable) {
t.Fatalf("nil listener dependencies error = %v", err)
}
listenerCtx, listenerCancel := context.WithCancel(context.Background())
listenerCancel()
RunCreatorEventListeners(listenerCtx, nil, nil, nil, nil, nil)
}
func TestHandleCreatorGatewayEventClassifiesNonNoticeEventsWithoutStore(t *testing.T) {
binding := creatorEventBinding{accountID: "account-1"}
for _, kind := range []string{"error", "reconnected", "open", "baseline", "close", "unknown"} {
handleCreatorGatewayEvent(context.Background(), nil, binding, creatorGatewayEvent{Kind: kind}, nil, nil)
}
handleCreatorGatewayEvent(context.Background(), nil, binding, creatorGatewayEvent{Kind: "notice"}, nil, nil)
handleCreatorGatewayEvent(context.Background(), nil, binding, creatorGatewayEvent{
Kind: "notice",
Notice: &creatorGatewayEventNotice{EventKey: "1", EventType: "comment", InteractorUID: "123"},
}, nil, nil)
binding.env = hub.EnvironmentContext{Env: hub.Env{Alias: "account-1"}, RuntimeID: "runtime-1", RuntimeNetworkID: "network-1", BindingVersion: 1}
if got := creatorListenerGeneration(binding.env); got != "runtime-1:network-1:1" {
t.Fatalf("listener generation = %q", got)
}
}