At my job we've found working with MSW + OpenAPI to be near miraculous. I work on a web frontend and do most of my development against a mock API powered by MSW. This live preview runs against the mock API running fully in-browser.
After buying in to OpenAPI as the fundamental source of truth (generated via https://www.ts-rest.com contracts in my case), I have radically changed how I think about web development.
At this point, it's frankly absurd to me how many people out there make it so hard for themselves by manually building/typing/validating both client & server-side responsibilities in most typical REST setups. I get it -- I spent >2 decades in that reality, but no more. I will die on this hill.
I am likely understating the impact when I say I'm 2x as productive whenever I touch API related functionality/validation on client or server-side.
MSW, Zod, react-hook-form+ZodResolver and several other tools in the OpenAPI ecosystem are simply incredible for productivity. The project I'm on now is certainly the most fun I've ever built because of these amazing tools.
we started using (and now contributing to) https://orval.dev/ this year which both generates the mocks using MSW as well as the client-side networking code (React Query in our case). It removes so much boilerplate its amazing.
Orval is great, I also recently wrapped up a project with Orval, React Query, and MSW. Generated my typescript models, helped me track changes in the API each time I updated against the swagger spec and let me test and demo the UI before our API team had a server running. Such a time-saver.
We more or less did that too. We generate typed wrappers for every handler, and then we manually implement the internal logic for each endpoint. I doubt reliably generating 100% of the logic is possible, but even if it is, I would guess it's more work to do that than to do it manually.
I'm so glad to see all of your comments here. I've been fascinated by your setup ever since hearing about it on the Oxide and Friends podcast. The part that I'm most curious about is the part where you weave together auto-generated interface code with hand-implemented mock implementations… I'll have to go read your code and see how that happens.
[Edit, after reading a bit of the code]
Am I correct in understanding that the generated code maps API calls to a typed interface, and then the hand-built implementation simply implements that interface?
So rather than complex weaving where you want hand-coded function bodies but generated signatures, you have generated signatures, where each function body calls a method on a generated interface.
Yeah, basically. We do it with a function call where the argument to the function is that interface representing all the API endpoints. `makeHandlers` handles parsing path params, query params, and request body and passes them to each endpoint handler. So the runtime validation of request bodies is also generated — we generate a zod schema for each request body in the OpenAPI definition and use it to parse the actual request body that comes in. So it's not just a generated interface — there is also generated runtime behavior that is endpoint-specific.
It's all mocked, so you're not really Hannah, and you're not really launching instances. Their console is open source, and when you run it in dev mode locally this is also what you see.
Also, worth pointing out that Hannah Arendt (the name that shows up as the logged in user) is a famous historian and philosopher (https://en.wikipedia.org/wiki/Hannah_Arendt)
Just when I think I get the whacky web kids, hell, that maybe I've even one of them, an article like this and functionality like this comes along.
I don't know how a mock library enables a revolution of having test data.
I don't know why the library couldn't change it's favorite method signature because a subset of versions of one JS framework couldn't...fetch?
or why the mock library can only have one dependency...
...and I feel _really_ out of the loop because I can't understand the tone, hinting at years of sweat and though that I'm more used to from a consumer product launch.
But that's why I respect the web more than ever. The reaction is real, and it means something, even if I don't understand it. People put _years_ into making (gestures) this work, so millions of developers can benefits, so billions, hell, _humanity_ can benefit. All in the open.
Worth noting that in my experience it's the combination of MSW and code generated from an OpenAPI spec that really makes it special, not just MSW alone.
The other reply covers it but I want to slice it slightly differently. I see two things that are different here. One is mocking at the HTTP boundary rather than mocking, e.g., function return values or modules or whatever. That's certainly not revolutionary (I know people do it with rspec and I'm sure plenty of test frameworks do it too), and in theory you could build your mock server with any tool that lets you build a server. But people don't usually do this, and when they do they tend to do it bit by bit for each test rather than thinking about it as mocking the entire API. So for example, in my mock API, my POST creating a project actually creates a project in a mock database, and then when I list projects, I can see what I just created. So I can test the UI by doing exactly what you would do manually — create the thing and see that it shows up where it's supposed to. All of that is built independently of my test for that feature, and it works for all the tests I write — I don't have to think about mocking API bits for a particular test.
The other thing that's unusual is running this mock in a Service Worker, which means it can run in the browser. That's pretty cool and pretty unique to this tool. But the Mock part is about running the same server outside of the browser i.e., in Node (or now Deno or Bun), which means you can use it for unit tests. So I think the thing you have to see here is the synthesis of all that in one thing — it's one mock server that (because it's written in JS) can run both in the browser and on the server. I admit it doesn't sound that great until you try it, but it enables some cool and surprisingly useful stuff like the live preview I linked.
Thank you __very__ much, I went a bit long to try to signal I was serious and thought I wouldn't get any substantive reply. This is beyond my wildest dreams. Thanks again.
> I don't know how a mock library enables a revolution of having test data.
From my understanding this isn’t (just) mock data, it’s an entire mock backend that runs inside the browser. To be able to simulate that with zero dependencies outside the browser does simplify a lot of testing scenarios.
Agreed. The more non-intrusive your APIs are, the better the overall experience is going to be for developers. Diverging from official/standard APIs means higher chance framework lock-in, which has kept me away from a lot of tooling.
Always try to ask myself when adding tooling: What's the chance I'll want to remove this later, and how painful is that going to be?
How do folks test timing-related stuff with MSW? AFAIK, MSW doesn't get along with jest.useFakeTimers. It drives me nuts; I have a bunch of disabled tests in an open-source project and at least one that is flaky because it uses real timers where I'd like to be using fake timers. [1, 2]
I've been thinking about ripping out MSW from my tests in favor of my own API-level mock for this reason. But it seems like many other folks are happy with MSW. I have to assume there's something I'm not getting. I'm a fish out of water with frontend stuff in general...
Super excited to see this land. I've been following this closely and experimenting with the beta branch; the ability to swap out real network requests with mocked ones in process is a huge upgrade for any kind of work you might have wanted to do with a proxy.
You can generate TS from an OpenAPI spec and then create type-safe mocks of network calls.
Basic mocks and fake servers run the risk of falling out of sync and giving false positives, or just being outright wrong to short-cut some of the work. It's also less code to maintain when a service worker can intercept the call, instead of orchestrating a load of mock APIs.
It won't stop you making breaking changes on the API but it will keep you honest on consuming the API on the client.
Too bad this only gets you so far. Last time I checked, the OpenAPI specs are not as flexible as TS types and the people who author these - probably the team members responsible for the backend - won't necessarily even be able to list all the invariants due to framework and host language constraints. And OpenAPI does not support WebSockets. The project I work on has a frontend written in TypeScript, a Java backend, an Express-based dev-server that shares same types with FE, but none of the solutions the team evaluated enables the type sharing across all three beyond simple "an object can have these fields" - no algebraic data types, no WebSocket support. In the end, we resorted to agreeing on as much as possible in plain text before greenlighting the new endpoint, and then double checking the implementation and client usage for unexpected behaviors.
For those use-cases you might just be better off with either contract tests or simply making the payload itself typesafe with something like protobuf.
OpenAPI/Swagger is basically inextricably bound to REST/JSON APIs over HTTP. I also think they're quite abstruse in terms of defining non-trivial interfaces.
One of the biggest advantages of MSW, is that you can use the same mock server in your unit tests (jest) on Node.js environment and run the full frontend in the Browser for development and preview.
The best if you have totally the same mock data, so super easy to debug your tests.
Also, you can use this trick to have scenarios, so you can demo different behaviours just by passing a query param. QA loves it as well.
For me, the fact that every dev server tab I open is its own fresh server instance is really useful. We can run our tests in parallel with no server. We can deploy a live preview as a static site.
I have the same question. I just use a small local container fleet (Docker Compose) and have my actual API server running, and have never seen this to be a problem. I can do all this local development without depending on connectivity, etc.
Sure, it's a lot of fanfare, but at my job we've found working with MSW + OpenAPI to be near miraculous. I work on a web frontend and do most of my development against a mock API powered by MSW. This live preview runs against the mock API running fully in-browser.
I don't think they have VC money. I think the people building it just know what they're doing. Do you see anything that indicates this is a VC-funded project? It looks to me like they're only getting a little bit of money from Github Sponsors (https://github.com/sponsors/mswjs).
That's a lot of time and effort, for people earning next to nothing, for an open-source library. I'm not saying it's bad they have a beautiful website to rival any small SaaS, but how is even possible they have the time and energy to spend on that, rather than on the code itself? What would Linux or GNOME or leftpad look like with a proportional amount of marketing effort?
Last time I checked, testing libraries did not have custom iconset and a testimonial section to rival the Stripe homepage.
I think this is actually pretty common in the JavaScript ecosystem. Presumably, because contributors are very skilled in building websites and maybe also because users have higher expectations when it comes to presentation. I mean checkout https://vitest.dev/https://jestjs.io/https://webdriver.io/de/https://playwright.dev/ (all testing related stuff).
1. It's actually pretty easy to get a pretty site these days. The SaaS layout is so standardized you can just buy a template to get your React site up and running and looking professional for a couple hundred dollars and a few hours of work. The site overall definitely took more time than that.
2. This is a library for front-end developers. It's made by front-end developers who probably have some design skills of their own. That makes it easier for them than Linux's kernel hacker team to set up a nice website.
3. Is this just a matter of insecurity on your part? I'm sure you have plenty of dev skills but maybe they don't extend to UI and you don't like that this team can throw together a beautiful site for something that's merely a side-project?
I'm not sure what you're getting at here. Not all open source projects are trying to turn users into products.
A lot of open source projects derive value from getting external contributions that they wouldn't otherwise if something was kept closed source and in-house. Paying for software isn't always necessary.
So when I use, say, ffmpeg: In what sense am I their product?
They don’t collect telemetry, they don’t serve me ads, the output can be used with any other tool so there’s no lock in, there’s no FFmpeg Pro (TM) with features withheld from the base version.
This seems a little silly I know, but GP was talking about open source projects and you literally said “I can’t find any exception”.
If you can’t find any exception then you’ve missed like 80% of the FOSS ecosystem. Incl every BSD, most linuxes, most python libs and so on and so forth.
Stuff like Blink, it's designed to be a free-as-possible, scorched-earth-tactics moat so anyone trying to be "funny" and locking down/monetizing the platform in other ways other that the major contributor "blessed ways" are screwed up.
In a way, the "freeest" tech around is the one that promotes "commoditize your complement", as that is the most capitalist incentive one has to have your cake and eat it, too.
> Along the way, I noticed something interesting about open source software, which is this: most of the companies spending big money to develop open source software are doing it because it’s a good business strategy for them, not because they suddenly stopped believing in capitalism and fell in love with freedom-as-in-speech.
> (...) All else being equal, demand for a product increases when the prices of its complements decrease.
> Let me repeat that because you might have dozed off, and it’s important. Demand for a product increases when the prices of its complements decrease.
https://oxide-console-preview.vercel.app
More details:
https://github.com/oxidecomputer/oxide.ts
https://github.com/oxidecomputer/console
https://oxide.computer/podcasts/oxide-and-friends/1426644
Really excited about this next step for MSW — we'll be upgrading soon. Building on web standards buys you so much.
(Reposted at top level because the parent got flagged.)