89 lines
2.3 KiB
Go
89 lines
2.3 KiB
Go
//go:build dev
|
|
|
|
package bundler
|
|
|
|
import (
|
|
"bufio"
|
|
"net"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
// A real TCP client completes the WebSocket handshake against the hub (exercising
|
|
// the http.Hijacker path a recorder can't), then receives a broadcast frame. This
|
|
// covers the end-to-end push channel the browser HMR client relies on.
|
|
func TestWebSocketHandshakeAndBroadcast(t *testing.T) {
|
|
h := newHub()
|
|
mux := http.NewServeMux()
|
|
mux.HandleFunc("/@hmr/ws", h.ServeWS)
|
|
srv := httptest.NewServer(mux)
|
|
defer srv.Close()
|
|
|
|
conn, err := net.Dial("tcp", strings.TrimPrefix(srv.URL, "http://"))
|
|
if err != nil {
|
|
t.Fatalf("dial: %v", err)
|
|
}
|
|
defer conn.Close()
|
|
|
|
_, err = conn.Write([]byte(
|
|
"GET /@hmr/ws HTTP/1.1\r\n" +
|
|
"Host: " + srv.Listener.Addr().String() + "\r\n" +
|
|
"Upgrade: websocket\r\n" +
|
|
"Connection: Upgrade\r\n" +
|
|
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" +
|
|
"Sec-WebSocket-Version: 13\r\n\r\n",
|
|
))
|
|
if err != nil {
|
|
t.Fatalf("write handshake: %v", err)
|
|
}
|
|
|
|
br := bufio.NewReader(conn)
|
|
status, err := br.ReadString('\n')
|
|
if err != nil || !strings.Contains(status, "101") {
|
|
t.Fatalf("expected 101 Switching Protocols, got %q (err %v)", status, err)
|
|
}
|
|
var acceptOK bool
|
|
for {
|
|
line, err := br.ReadString('\n')
|
|
if err != nil {
|
|
t.Fatalf("reading headers: %v", err)
|
|
}
|
|
if strings.HasPrefix(line, "Sec-WebSocket-Accept:") &&
|
|
strings.Contains(line, "s3pPLMBiTxaQ9kYGzzhZRbK+xOo=") {
|
|
acceptOK = true
|
|
}
|
|
if line == "\r\n" {
|
|
break
|
|
}
|
|
}
|
|
if !acceptOK {
|
|
t.Fatal("missing/incorrect Sec-WebSocket-Accept header")
|
|
}
|
|
|
|
// The client must be registered before we broadcast.
|
|
deadline := time.Now().Add(2 * time.Second)
|
|
for h.clientCount() == 0 && time.Now().Before(deadline) {
|
|
time.Sleep(5 * time.Millisecond)
|
|
}
|
|
if h.clientCount() != 1 {
|
|
t.Fatalf("hub client count = %d, want 1", h.clientCount())
|
|
}
|
|
|
|
h.broadcastJSON(hmrMessage{Type: "full-reload"})
|
|
|
|
conn.SetReadDeadline(time.Now().Add(2 * time.Second))
|
|
op, payload, err := readFrame(br)
|
|
if err != nil {
|
|
t.Fatalf("reading broadcast frame: %v", err)
|
|
}
|
|
if op != opText {
|
|
t.Errorf("broadcast opcode = %#x, want text", op)
|
|
}
|
|
if !strings.Contains(string(payload), `"full-reload"`) {
|
|
t.Errorf("broadcast payload = %q, want full-reload message", payload)
|
|
}
|
|
}
|