WebSocket Support Beta #2010
Replies: 20 comments 47 replies
-
Allow preventing connection-level actionsRight now, if a handler has some action on the connection event, like greeting any connected client, it's impossible to opt-out from that behavior completely: api.on('connection', ({ client }) => client.send('hello'))
server.use(
api.on('connection', ({ client }) => ???)
) No matter what you do in the override handler, the connected client will always receive api.on('connection', (event) => {
event.client.send('hello')
})
server.use(
api.on('connection', (event) => {
event.stopImmediatePropagation()
event.client.send('howdy')
})
)
Downsides:
|
Beta Was this translation helpful? Give feedback.
This comment has been hidden.
This comment has been hidden.
-
Routing events through Service WorkerAll data sent by WebSocket is transferable: string, blob, arraybuffer. We can route the connection through the Service Worker. Here's why we should consider doing so:
There are some minor downsides to this too. Mainly, the browser and Node.js handling of WebSocket events will be different internally. This doesn't affect the developer's experience in a negative way. If anything, it may improve DX by providing a consistent
|
Beta Was this translation helpful? Give feedback.
This comment has been hidden.
This comment has been hidden.
This comment has been hidden.
This comment has been hidden.
This comment has been hidden.
This comment has been hidden.
-
Hi @kettanaito I was looking at and looking forward to the websocket support. Is it possible to clarify what is meant with "MSW will only support mocking WebSocket connections implemented via the WHATWG WebSocket API"? How can I find out if what is running via websocket is supported by MSW? Specifically, I'm trying to get it to work with https://github.com/enisdenjo/graphql-ws/, but Would be cool to have a bit more info about this. And possibly a debug mode where MSW intercepts all Websocket connections and shows if it can work with them? Idk if this is even possible, just a thought. |
Beta Was this translation helpful? Give feedback.
-
Add loggingWould be great to add logging for outgoing and incoming events like what we have for HTTP requests. Twice as useful given the interception takes away the observability in the Network tab. |
Beta Was this translation helpful? Give feedback.
-
Hi @kettanaito Can you add a Jest (yes, I know you are not a fan :-) ) example as well? I am wondering how you envision the handling of events within a specific jest test or group of tests. |
Beta Was this translation helpful? Give feedback.
-
Unhandled connectionsWith the introduction of a new protocol to MSW, I consider adding different protocol-based options to the server.listen({
http: {
onUnhandledRequest({ request, print }) {}
},
ws: {
onUnhandledConnection({ client, print }) {}
}
}) This can help greatly to decouple the configurations for different protocols, such as mocking, debugging, handling of unhandled requests/connections. |
Beta Was this translation helpful? Give feedback.
This comment has been hidden.
This comment has been hidden.
This comment has been hidden.
This comment has been hidden.
-
Hello guys! Thanks for your work. Any idea if this would work with |
Beta Was this translation helpful? Give feedback.
This comment has been hidden.
This comment has been hidden.
-
Hi folks 👋 - I'm looking into this to try using it in Jest + node but I haven't been able to get it working (I never get an open event in the WebSocket instance). Is there any canonical example that's up-to-date where I can find it working? |
Beta Was this translation helpful? Give feedback.
This comment has been hidden.
This comment has been hidden.
This comment has been hidden.
This comment has been hidden.
-
Hello! I think I'm missing something here. I have a Node.js server that is a sort of coordination layer - it is both a websocket server (for browser clients) and a websocket client (streaming with 3rd party services). So I've been able to use Until now, I've been using the excellent and widely adopted import { WebSocket } from 'undici'
import { ws } from 'msw'
const url = 'ws://localhost/stream'
const mockServer = ws.link(url)
it('connects', (done) => {
mockServer.on('connection', () => done())
new WebSocket(url)
}) Result: test timeout ( Am I missing something here? Note that |
Beta Was this translation helpful? Give feedback.
-
Proposal: Connection-wide message encoding/decodingThe way we support custom WebSocket clients like SocketIO is through the concept of a binding. Binding applies itself on the connection object (the argument to the I propose we moved that logic up to the const api = ws.link('wss://example.com', {
encode: (messageEvent) => {},
decode: (messageEvent) => {}
}) My reasoning is this:
The interceptor will know when to apply the The bindings usage would then look like this: import { binding } from '@mswjs/socket.io-binding'
const api = ws.link('wss://example.com', {
encode: binding.encode,
decode: binding.decode,
}) Just need to check if bindings are designed to do more than message encoding. |
Beta Was this translation helpful? Give feedback.
-
Hi! Thanks for finding time to share your feedback on the WebSocket support in MSW!
Goals
The main goal behind this RFC is to gather feedback on the WebSocket interception API in MSW and give the beta release a try once it's out.
Before you begin
Important
MSW will only support mocking WebSocket connections implemented via the WHATWG WebSocket API. We are committed to the standard-driven API mocking, and that includes WebSockets! The
WebSocket
API is globally available in the browser, and it's also coming to Node.js this year (already available as an experimentalWebSocket
API inundici
).Getting started
Install the
msw@next
package to get the work-in-progressws
API:ws
APIGeneral statements
server.connect()
.event.preventDefault()
in the relevant server event listener.Questions
ws.url
orws.link
? I'd like to have consistency withgraphql.link
so one of them should be renamed.ws.link()
for consistency.ws
"event handlers" are self-contained, meaning that they don't follow the usual request resolution pipeline (request -> handlers list -> response). But I still wish for WebSocket logic to be placed alongside the rest of your handlers..use()
). How should these work? Once again, thews
API is self-contained. It will dispatch the "connection" event to allws
interceptors but there's no conventional event propagation here to stop to support a fallthrough behavior akin to request handlers.return
but viaevent.stopImmediatePropagation()
. This supports opting-out even from individualclient
/server
events as those share the same event instance across multiple listeners and even WebSocket event handlers.Beta Was this translation helpful? Give feedback.
All reactions