github.com/martinohmann/rfoutlet@v1.2.1-0.20220707195255-8a66aa411105/internal/websocket/client_test.go (about) 1 package websocket 2 3 import ( 4 "context" 5 "net/http" 6 "testing" 7 "time" 8 9 "github.com/gin-gonic/gin" 10 "github.com/martinohmann/rfoutlet/internal/command" 11 "github.com/posener/wstest" 12 "github.com/stretchr/testify/assert" 13 "github.com/stretchr/testify/require" 14 ) 15 16 func TestClient_listenRead(t *testing.T) { 17 tests := []struct { 18 name string 19 data interface{} 20 expectedCmdType command.Command 21 }{ 22 { 23 name: "outlet action", 24 data: map[string]interface{}{ 25 "type": "outlet", 26 "data": map[string]string{ 27 "action": "on", 28 "id": "foo", 29 }, 30 }, 31 expectedCmdType: &command.OutletCommand{}, 32 }, 33 { 34 name: "status action", 35 data: map[string]interface{}{ 36 "type": "status", 37 }, 38 expectedCmdType: &command.StatusCommand{}, 39 }, 40 { 41 name: "unknown command", 42 data: map[string]interface{}{ 43 "type": "foo", 44 }, 45 }, 46 } 47 48 for _, test := range tests { 49 t.Run(test.name, func(t *testing.T) { 50 hub := NewHub() 51 52 queue := make(chan command.Command) 53 54 r := gin.New() 55 r.GET("/ws", Handler(hub, queue)) 56 57 c, _, err := wstest.NewDialer(r).Dial("ws://localhost/ws", nil) 58 require.NoError(t, err) 59 defer c.Close() 60 61 go func(data interface{}) { 62 require.NoError(t, c.WriteJSON(data)) 63 }(test.data) 64 65 ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond) 66 defer cancel() 67 68 go hub.Run(ctx.Done()) 69 70 select { 71 case <-ctx.Done(): 72 if test.expectedCmdType != nil { 73 t.Fatal(ctx.Err()) 74 } 75 case cmd := <-queue: 76 if test.expectedCmdType == nil { 77 t.Fatalf("did not expect command, but got %T", cmd) 78 } 79 80 assert.IsType(t, test.expectedCmdType, cmd) 81 } 82 }) 83 } 84 } 85 86 func TestClient_listenWrite(t *testing.T) { 87 stopCh := make(chan struct{}) 88 defer close(stopCh) 89 90 hub := NewHub() 91 go hub.Run(stopCh) 92 93 queue := make(chan command.Command) 94 95 r := gin.New() 96 r.GET("/ws", Handler(hub, queue)) 97 98 c, rr, err := wstest.NewDialer(r).Dial("ws://localhost/ws", nil) 99 require.NoError(t, err) 100 defer c.Close() 101 102 assert.Equal(t, http.StatusSwitchingProtocols, rr.StatusCode) 103 104 ctx, cancel := context.WithTimeout(context.Background(), 200*time.Millisecond) 105 defer cancel() 106 107 go func() { 108 // give the client some time to register to hub before broadcasting 109 <-time.After(20 * time.Millisecond) 110 hub.Broadcast([]byte(`{"name":"bar"}`)) 111 112 <-ctx.Done() 113 c.Close() 114 }() 115 116 type foo struct { 117 Name string 118 } 119 120 val := foo{} 121 122 require.NoError(t, c.ReadJSON(&val)) 123 assert.Equal(t, foo{Name: "bar"}, val) 124 }