Files
kefu/im/backend/internal/app/im_realtime_client_integration_test.go
2026-09-03 08:38:17 +08:00

65 lines
2.3 KiB
Go

package app
import (
"context"
"encoding/json"
"net/http/httptest"
"os"
"os/exec"
"path/filepath"
"testing"
"time"
"github.com/zeromicro/go-zero/rest/handler"
"github.com/zeromicro/go-zero/rest/router"
)
// Opt-in local cross-stack test. All identities and messages live in a unique,
// disposable schema created by isolatedIMDatabase, never IM or a remote server.
func TestIMRealtimeClientMySQL(t *testing.T) {
if os.Getenv("IM_TEST_MYSQL_DSN") == "" {
t.Skip("set IM_TEST_MYSQL_DSN for the isolated local client/server test")
}
node, err := exec.LookPath("node")
if err != nil {
t.Fatal("Node.js is required for the cross-stack IM test")
}
script, err := filepath.Abs(filepath.Join("..", "..", "..", "mobile", "scripts", "im-realtime.integration.mjs"))
if err != nil {
t.Fatal(err)
}
db := isolatedIMDatabase(t)
a := &App{db: db, hub: NewHub(), config: Config{Environment: "development", JWTSecret: "isolated-realtime-client-secret-only"}}
mux := router.NewRouter()
for _, route := range a.userRoutes() {
// Exercise real routing, JWT auth, request middleware and Go-zero timeout
// middleware (including its WebSocket exemption), not identity injection.
if err := mux.Handle(route.Method, route.Path, handler.TimeoutHandler(35*time.Second)(a.requestMetadata(route.Handler))); err != nil {
t.Fatal(err)
}
}
server := httptest.NewServer(mux)
defer server.Close()
tokens := make([]string, 3)
for i := range tokens {
tokens[i], err = a.token(int64(i+1), "user", "isolated-fixture", 5*time.Minute)
if err != nil {
t.Fatal(err)
}
}
config, _ := json.Marshal(map[string]any{"origin": server.URL, "tokens": tokens})
ctx, cancel := context.WithTimeout(context.Background(), 55*time.Second)
defer cancel()
command := exec.CommandContext(ctx, node, script)
command.Env = append(os.Environ(), "IM_REALTIME_FIXTURE="+string(config))
output, err := command.CombinedOutput()
if err != nil {
t.Fatalf("client/server realtime regression failed: %v\n%s", err, output)
}
t.Log(string(output))
var markedRead int
if err := db.QueryRow(`SELECT COUNT(*) FROM im_conversation_members WHERE user_id=2 AND read_seq>0`).Scan(&markedRead); err != nil || markedRead != 0 {
t.Fatalf("staying on the list must never acknowledge incoming messages: count=%d err=%v", markedRead, err)
}
}