MSW 2.0 – Mock Service Worker(mswjs.io) |
MSW 2.0 – Mock Service Worker(mswjs.io) |
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.)
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.
wrote up the basics of our workflow few weeks ago https://betaacid.co/blog/api-contracts
Feel free to email me at mish@stepci.com if you want to hear more!
Generator: https://github.com/oxidecomputer/oxide.ts/blob/64401fa2/gene...
Generated output: https://github.com/oxidecomputer/console/blob/8e74accf/libs/...
Manually implemented endpoint behavior: https://github.com/oxidecomputer/console/blob/8e74accf/libs/...
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?
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...
[1] https://github.com/scottlamb/moonfire-nvr/blob/5ea5d27908f1a...
[2] https://github.com/scottlamb/moonfire-nvr/blob/5ea5d27908f1a...
Congrats on the release!
"Please enable ads on this website. Thank you."
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.
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.
https://github.com/zoltan-nz/meetup-contacts-app-2021/blob/m...
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.
[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.
big function call https://github.com/oxidecomputer/console/blob/bd65b9da7019ad...
automatic body parsing and argument passing: https://github.com/oxidecomputer/console/blob/bd65b9da7019ad...
When an endpoint gets added to the spec, we can rerun the generator and get type errors in the `makeHandlers` telling us endpdoints are missing.
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.
Shine on, you crazy diamonds. https://www.youtube.com/watch?v=54W8kktFE_o
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.
Worth a read: https://kentcdodds.com/blog/stop-mocking-fetch
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.
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.