mswjs / msw

Seamless REST/GraphQL API mocking library for browser and Node.js.
https://mswjs.io
MIT License
15.29k stars 481 forks source link

Support mocking WebSocket APIs #156

Open Doesntmeananything opened 4 years ago

Doesntmeananything commented 4 years ago

Is it possible to use msw to mock server-sent events (SSE) and WebSocket (WS) connections?

My use case is to have a somewhat full client-side mocking story (including REST, SSE, and WS functionality), and since msw is such a joy to use when mocking out REST APIs, I was wondering if it makes sense to use it to mock more specialised server interactions.

Have you thought about this? I admit that I haven't looked much into whether it's possible just to use custom request handlers to add this functionality, emulating SSE and WS behaviour in some way. I wanted to know if you already had something in mind regarding this question. Thanks!

kettanaito commented 9 months ago

September 2023 Status Update

https://github.com/mswjs/interceptors/pull/236#issuecomment-1691251251

@Stackustack, supporting SSE is unfortunately not enough to ship WebSocket support. See the status update in the linked comment above.

kettanaito commented 5 months ago

Update

I've had some success implementing a WebSocket class-based interceptor (https://github.com/mswjs/interceptors/pull/501). This means that the WebSocket support is coming to MSW rather soon! The browser test suite is currently passing. The Node.js test suite using Undici's WebSocket as a global is also passing!

Now, before anyone gets overly excited about this, let me clarify a few things.

  1. MSW will only support intercepting a WebSocket communication established by using the global WebSocket class (i.e. the WHATWG WebSocket standard present globally). This means that third-party libraries that implement WebSockets by other means (e.g. using custom transports) will not be supported. I see no future in supporting contrived transports from third-parties—that is an unreliable strategy. I'd much rather see (and even help) those third-parties migrate to use the standard, as it's also landing in Node.js later this year.
  2. The API to intercept and work with WebSockets will respect the WHATWG WebSocket Standard. This means you will receive outgoing MessageEvent and send back data that will be translated to an incoming MessageEvent.

What's left?

Feedback. You can help land this API sooner by helping with the following:

Meanwhile, I will improve the test coverage of the interceptor to make sure it's fully compatible with the standard when you're using it.

kettanaito commented 5 months ago

Turns out that the initial WebSocket implementation will support SocketIO also!

If you want to be able to mock SocketIO with MSW, please read and upvote this: https://github.com/socketio/socket.io-parser/issues/129

Thank you.

kettanaito commented 5 months ago

WebSocket Support Beta

Please participate in the discussion about the upcoming WebSocket API to help us shape it and ship it faster:

Thank you!

kettanaito commented 4 months ago

I'm renaming this issue so it focuses on the WebSocket API mocking exclusively.

Server-Sent Events (SSE) are quite different, and to my best knowledge, they can be intercepted by the Service Worker. Their implementation will be different. If someone needs it, I encourage you to open a new feature proposal and describe it in more detail (e.g. how you are using SSE in your application, how you imagine mocking to look like, etc).

kettanaito commented 3 months ago

Update: Give the RC a try!

You can install the RC with the WebSocket support today: npm i msw@next.

Please participate and share your feedback! The more feedback we get, the faster and better the end API will be released. Thank you!

95th commented 3 months ago

@kettanaito I am getting when using websocket mocks:

ReferenceError: BroadcastChannel is not defined
    at file:///<project>/node_modules/.pnpm/msw@2.3.0-ws.rc-1_typescript@4.8.4/node_modules/msw/src/core/ws/ws.ts:14:28
    at ModuleJob.run (node:internal/modules/esm/module_job:193:25)

Code I am trying:

    const api = ws.link("wss://foo.bar.com/baz");
    const apiHandler = api.on("connection", ({ client }) => {
        client.addEventListener("message", event => {
            // Echo the message back to the client
            client.send(event.data);
        });
    });

Platform: Node

kettanaito commented 3 months ago

@95th, hi! What version of Node.js are you running? It looks like it's older than v18.

MSW itself doesn't support Node.js <18. Please update and have the global BroadcastChannel API available!