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) } }