Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds WebSocket support #396

Closed
wants to merge 7 commits into from
Closed

Adds WebSocket support #396

wants to merge 7 commits into from

Conversation

kettanaito
Copy link
Member

@kettanaito kettanaito commented Sep 23, 2020

GitHub

Goal

Provide a designated API that would allow the mocking of a WebSocket server. Keep the API as close to the actual server's API as possible, to minimize the library-specific knowledge needed to operate with this API.

Changes

  • Adds basic classes for WebSocket support.
  • Adds integration tests.

Roadmap

  • Support execution in Node.js.
    • Utilize WebSocketStorage class as a singleton to store all server references.
    • There is no Event in Node.js.
    • There is no BroadcastChannel in Node.js (not needed, we can use singletons in Node.js).
  • Integration tests
    • Server error event.
    • Server close event.
    • Ensure client does not receive messages when it's being closed (gets removed from the internal connections list of the server).
    • Test multi-tab event propagation
  • Ensure there are no memory leaks when multiple clients (tabs) are opened.

@kettanaito
Copy link
Member Author

How to try this out?

Building locally

  1. Clone the msw repository, checkout the websocket-support branch, and yarn build the library.
  2. Link the local build via npm link.
  3. Use in your project by npm link msw.

API references

See the test/ws-api integration tests (the *.mocks.ts files) for usage examples and API references. See type definitions for more information about the API.

@ashkan-pm
Copy link

Love the library, we need this feature for our company since we have already integrated MSW in our workflow. If there is anything I can do here to help please give me some direction.

@kettanaito
Copy link
Member Author

Hey, @ashkan-pm. Thanks for reaching out! The best thing you can do at the moment is to give this branch a test in your project. Share the feedback and bugs you spot here. See the instructions above.

I may have other things that need help in the future.

@keremciu
Copy link

I love using msw for different projects, I will give a shot on new version of my game

https://github.com/keremciu/house-of-decks/blob/ws-implement/client/src/utils/server-mock.js I use mock-socket and it kinda worked, let me see how this would work

import { captureConsole } from '../../support/captureConsole'
import { runBrowserWith } from '../../support/runBrowserWith'

test('sends server event to all active clients', async () => {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this test is great! I'd like to try it out in my tests, thanks for all this hard work here ✨

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, @keremciu. So far it behaves as expected in regards to multi-client handling. Please let me know once you try this out.

@johnico
Copy link

johnico commented Jan 2, 2021

Hi is there will be suppirt also for socket.io ?

@kettanaito
Copy link
Member Author

Hey, @johnico. We are planning on socket.io support as it's one of the most used WebSocket libraries. I'm not sure if there're any usage examples with it yet, but I'd be glad to work on them when the time comes.

@johnico
Copy link

johnico commented Jan 3, 2021

@kettanaito thanks
so for now I can you the library for rest actions and create another "real" server for the socket.io support (for example send an event when the test has been loaded or by rest call that will "Send" an event to the client)
do you thing that should work with cypress ?

@kettanaito
Copy link
Member Author

@johnico the easiest way is just to try that out. WebSocket events are not captured by Service Workers, so there should be no issue with having MSW for mocking REST API and provisioning a separate mock WebSocket server by yourself to deal with WebSockets. The only issues there can be are in NodeJS, because request interception works differently there.

@ghost
Copy link

ghost commented Apr 5, 2021

@kettanaito - Is there any idea on when this feature will be released?

@kettanaito
Copy link
Member Author

kettanaito commented Apr 6, 2021

@josh-biddick, there's no release date planned for it yet. It needs to have a proof of concept in Node.js to see if WebSocket support is even possible in that environment. There are quite a lot of other tasks on the roadmap, with some taking precedence over this. While I see WebSocket support as a great addition to the library, there are features that much more developers would benefit from, objectively. The team behind the project is small, so there are not enough hands to get to some stuff.

If you wish to get this done sooner, consider contributing to the project, either by helping with the open issues or supporting the work on WebSockets on Open Collective. With enough funds, we can pay contributors to dedicate time to this feature exclusively.

Copy link

@jbcpollak jbcpollak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the build is probably failing because the code is trying to load webSocketStorage from WebSocketStorage.ts but the file is webSocketStorage.ts.

I'm not sure which is more idiomatic for the project, but I went with changing the code to look for the right file, rather than change the case of the filename.

src/ws/WebSocketOverride.ts Show resolved Hide resolved
src/ws/WebSocketServer.ts Show resolved Hide resolved
@PeterDierckx78
Copy link

PeterDierckx78 commented Oct 28, 2021

@kettanaito, Can you please fix the above mentioned typo please? File webSocketStorage.ts should be WebSocketStorage.ts.

@MatanBobi
Copy link
Contributor

Hi @kettanaito, need any help pushing this to the finish line? I have some spare time to help on it if needed :)

@daartv
Copy link

daartv commented Feb 15, 2022

Hey @kettanaito curious about the state of things with this, wonder if it might be coming to official support soon-ish

@lifeiscontent
Copy link

thought this article might be helpful for anyone interested in adding node.js support: https://dustinpfister.github.io/2019/11/20/nodejs-websocket/

@kettanaito
Copy link
Member Author

Hey, folks. Thank you everybody for contributing with feedback.

I am planning on getting to WebSocket support this spring. We've just released a massive Node.js request interception rewrite and I need some time to address any related issues. We are also migrating all our dependencies to Node.js v16 to stay up-to-date and prevent unexpected behaviors when using newer versions of Node.js.

My plan remains the same:

  1. Investigate how WebSocket works in Node.js (thanks @lifeiscontent for the article, I've read through it briefly and it looks fantastic);
  2. Implement a quick prototype in Node.js.
  3. Finalize the prototype and write tests.
  4. Potentially refactor the request handlers queue in MSW so that you could use ws in the same array with other handlers.

@MatanBobi, thanks for volunteering! I will certainly count you in once I reach the state of these changes where contributions would be easier. Right now it's a rough PoC and collaborating on it will not be efficient just yet.

As I'm getting overwhelmed with the issues, I feel this is a good time to remind everybody that you can sponsor Mock Service Worker on GitHub to, hopefully, accumulate the budget to have at least one part/full-time contributor. Until then happens, I will prioritize tasks and work on them as my time allows. Thank you for understanding.

@SerkanSipahi
Copy link

@kettanaito Thank you for hard work. I started sponsoring you :)

@kettanaito
Copy link
Member Author

Thank you, @SerkanSipahi! I appreciate it more than you know it!

I'm nearing the end of the "polishing" phase as most of the critical issues should be addressed by now. There are a few releases ahead for the things other contributors have worked on, it's time to publish them. And after that, unless we got a large number of issues again, I'm planning on switching to WebSocket support.

@SerkanSipahi
Copy link

@kettanaito I am used to reading the tests first and then looking at the documentation if necessary. Your tests (https://github.com/mswjs/msw/pull/396/files) are wonderfully written and very understandable. Thank you for that.

@kettanaito
Copy link
Member Author

Update: I've spent some time outlining the architecture that the ws handlers should have. I want to retain the current split of responsibilities:

  • There will be a WebSocket events interceptor on the @mswjs/interceptor's side (ambiguous interceptor since we want to support browser and Node.js).
  • The ws handler will not be burdened with events interception.
  • The ws handler will act just like the rest handler in terms that: it receives an intercepted event and decides whether it should handle it in any way.
  • The ws handler will describe the server-side behavior, just like rest and graphql do (this is generally what MSW does, WebSocket will be no exception).

I'm curious if the current implementation of the RequestHandler base class will be sufficient to implement the ws handler. I want to believe it will be, but it's not closed to modifications in any way.

I will start with the study on how WebSocket is usually implemented in Node.js, and will turn that study into a Node.js interceptor for WebSocket events. Excited to get these changes going!

@lifeiscontent
Copy link

lifeiscontent commented Mar 23, 2022

@kettanaito should probably make sure msw has support for both binary and text request/responses as that's a big reason why a lot of devs will move to a web socket. with binary protocols you can create channels via some extra bits in binary data. You can see an overview of how something like that might work here: https://www.youtube.com/watch?v=-OjYRDVlGZQ

@kettanaito
Copy link
Member Author

A great point, @lifeiscontent. Thanks for sharing the link as well.

Let me get the browser/Node.js interception working for WebSocket and then we can iterate on top of it to ensure binary support.

@SerkanSipahi
Copy link

@kettanaito what is the current state of websocket support in msw? :)

@kettanaito
Copy link
Member Author

Hey, @SerkanSipahi. The current status is that the WebSocket support is in development. I've done some ground work in the interceptors repository so interceptors are now event-based. This will also open up the possibility to handle non-HTTP interactions in interceptors.

The WebSocket support will be implemented in a form of a new interceptors (see mswjs/interceptors#236). You can also find the progress map in the referenced pull request. This pull request (396) is likely to be abandoned.

How can I help make WebSockets happen faster?

  • Support MSW organization so there's budget to develop things faster.
  • Review the WebSocket interceptor and help spot issues, missing tests, and voice your proposals. This is something I will encourage everybody to do, as I'm not using WebSockets actively myself and may be missing certain use-cases that should be reflected in the interceptor's API.

@kettanaito
Copy link
Member Author

To prevent confusion, I'm closing this pull request in favor of mswjs/interceptors#236. There will be additional work required on the MSW's side once the interceptor is merged, such as developing the ws API that'd largely copy what we've had in this pull request.

If you wish to contribute, mswjs/interceptors#236 is the correct place to do so.

@kettanaito kettanaito closed this May 9, 2022
@SerkanSipahi
Copy link

SerkanSipahi commented May 9, 2022

@kettanaito I am already supporting msw for 2 month :) ... but I can help in reviewing the code, too.

@kettanaito
Copy link
Member Author

@SerkanSipahi, my bad 😅 I'm thankful for your support. That's the reason I was able to kick off the interceptors refactoring and have already prepared in-browser support for SocketIO and native WebSocket class as a part of that referenced pull request! Thank you for supporting the project.

@kettanaito kettanaito deleted the websocket-support branch February 12, 2024 10:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support mocking WebSocket APIs
10 participants