-
Notifications
You must be signed in to change notification settings - Fork 9
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
feat: decouple from cross-fetch #24
Conversation
@IanVS I changed the workflow a bit, so you will have to approve it before it runs :) |
974044e
to
fca3d1e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall this seems like a huge improvement. Writing the code in TS is a big win, and relying on the global fetch removes the dependency on cross-fetch, which is great.
I took a first-pass at reviewing this, but did not yet test it out in my own project. I have a few minor requests here, some questions about changes to the tests, and one larger request to break out the auto-enabling changes to its own PR, so I can review and weigh the pros and cons of that separately from the decoupling from cross-fetch. This is already a big PR, breaking that out would help get this landed more quickly.
Thanks for all the effort here!
fca3d1e
to
0ac63b6
Compare
Pushes a new commit, changes:
|
@@ -13,8 +13,8 @@ requests. It's easy to setup and you don't need a library like `nock` to get goi | |||
for mocking under the surface. This means that any of the `vi.fn()` methods are also available. For more information on | |||
the vitest mock API, check their docs [here](https://vitest.dev/guide/mocking.html) | |||
|
|||
It currently supports the mocking with the [`cross-fetch`](https://www.npmjs.com/package/cross-fetch) polyfill, so it | |||
supports Node.js and any browser-like runtime. | |||
As of version 0.4.0, `vitest-fetch-mock` mocks the global [Fetch](https://developer.mozilla.org/en-US/docs/Web/API/Window/fetch) method, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@IanVS I assume the next version to be 0.4.0
here. Let me know if you have different ideas.
1922c9b
to
615a6f5
Compare
}); | ||
|
||
it('resolves with function returning object body and init headers', async () => { | ||
fetch.mockResponseOnce(() => Promise.resolve({ body: 'ok', init: { headers: { ding: 'dang' } } }), { | ||
fetch.mockResponseOnce(() => Promise.resolve<MockResponse>({ body: 'ok', headers: { ding: 'dang' } }), { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the only breaking change I would like to keep (and maybe should document).
This is because the original typings had:
export interface MockParams {
status?: number;
statusText?: string;
headers?: string[][] | { [key: string]: string }; // HeadersInit
url?: string;
/** Set >= 1 to have redirected return true. Only applicable to Node.js */
counter?: number;
}
export interface MockResponseInit extends MockParams {
body?: string;
init?: MockParams;
}
I changed this to:
export interface MockParams {
status?: number;
statusText?: string;
headers?: [string, string][] | Record<string, string>; // HeadersInit
url?: string;
/** Set >= 1 to have redirected return true. Only applicable to Node.js */
counter?: number;
}
export interface MockResponse extends MockParams {
body?: string;
}
since otherwise you have duplicated properties, making it very fuzzy imho.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 I think I'm on board with this, but let me stew on it just a bit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, I've convinced myself, the way it was before made no real sense. We should indeed document this, but the best place is probably in the release notes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for making the changes I asked for! This looks good to me, and my tests passed when I patched it into my existing project that uses it (though I don't use it very extensively, TBH).
I notice one final change here that I want to ask about. Previously it was up to the user to provide vi
to the createFetchMock
function. Now, you're importing it straight from vitest
. This makes me slightly nervous because it means we are relying on both this package and the user's code pulling the same version of vitest. We have a peer dependency on vitest, so theoretically it should work fine, but I've struggled more than I like to recall with different versions of packages being used by different dependencies causing very subtle and hard-to-troubleshoot bugs.
Can you talk a little about what you see as the pros & cons of this new approach here vs the explicit dependency injection we currently have? And furthermore, are you maybe willing to move that change to a separate PR (can group together with the auto-enabling if you'd like), so that we can keep this particular PR focused on decoupling from cross-fetch?
Other than that, I think this is ready to go!
"module": "NodeNext", | ||
"moduleResolution": "NodeNext", | ||
"lib": [ | ||
"es2022" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What would you think about extending https://www.npmjs.com/package/@tsconfig/node18?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I "extended" (copied) the version of https://github.com/total-typescript/tsconfig/blob/main/tsc/no-dom/library.json. It's very similar, and basically another opinionated preset based on Matt Pococks TSConfig cheat sheet.
Most important settings are (in my opinion):
module
/moduleResolution
should be eithernode16
ornodenext
when usingtsc
to compile into ESM. This is the case for both versions, although one sticks tonode16
and the other choosesnodenext
. I am not sure if there is any difference between the two at this point. I see most projects usenodenext
, so I wouldn't be surprised if they're just aliases with only semantic differences.target
should be compatible with Node 18 or higher,es2022
in our case. This is the case for both versions.- for libraries its important to use
"declaration": true
so we emit type-definitions as well (this important now, since we now only have.ts
files in our source), and also"sourceMap": true
for the same reason. - the other compiler flags are just additional (opinionated) tweaks on strictness and other optimizations.
- the
lib
can indeed be upgraded toes2023
for Node 18+
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 sounds good.
I see most projects use nodenext, so I wouldn't be surprised if they're just aliases with only semantic differences.
Yeah right now they're the same, the difference is that "NodeNext" will always be the latest, so if new features are introduced, they'll get picked up without changing anything in the config.
}); | ||
|
||
it('resolves with function returning object body and init headers', async () => { | ||
fetch.mockResponseOnce(() => Promise.resolve({ body: 'ok', init: { headers: { ding: 'dang' } } }), { | ||
fetch.mockResponseOnce(() => Promise.resolve<MockResponse>({ body: 'ok', headers: { ding: 'dang' } }), { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, I've convinced myself, the way it was before made no real sense. We should indeed document this, but the best place is probably in the release notes.
The signature change was one of the many changes I initially made. At that point it was more of a simple proof-of-concept, written from scratch, using this library as inspiration. When I started adding more and more back in, I started to consider it as some kind of fork (but still, with many different design decisions). Only later I decided to contribute this as a pull request to this project, and with that approach we have all the reason to be careful. I see no reason to break this interface now. That’s why reverted the change. 😉 Is there a difference? Well, that depends.
With the peer dependency approach, there is not really any value over providing the |
Added another small fix that prevented I can't find any remaining issues anymore. I'm quite confident about this PR. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome work, thanks, let's
whoops, spoke too soon, looks like there's a minor linting issue. |
fixed! |
Thanks for contributing this as a PR even though I'm sure it was much more annoying to do than just making a fork or new project. If you'd like to make more breaking change PRs, for things like auto-enable and relying on peer dependencies, I'd be happy to review/merge those as well before making a 0.4 release (or maybe we just go to 1.0.0 now). I think I'm on board with the peer dependency, though there are some edge cases that could still bite us, like npm automatically installing a peer dependency when it doesn't find one, and yarn doing weird things in monorepos sometimes. But I think in our case it's probably pretty low risk. |
No worries, it actually reminds me to care about breaking changes, which is absolutely a good thing!
My feeling right now is to release this as 0.4, then add new feature(s) in 0.5, and then keep 1.0 for when things are stable and maybe for introducing some breaking changes and/or mark some things as deprecated to clean things up (and remove them for real in 2.0). If you agree, I'd say, let's release and publish the new version. 🎉
As far as I can see, nothing changed there. Vitest was already a peer dependency before 😉 |
All right, this PR includes:
cross-fetch
by just patching the global fetch which should be present in all modern runtimes and browsers. That would close issue Allow Passing Customfetch
Values to Overridecross-fetch
Usage #22 and Replace or drop "cross-fetch" since it is outdated and obsolete #23.DOMException
.I added a new feature that automatically registers enables inthis feature was droppedbeforeAll
, resets inbeforeEach
and disables inafterAll
(not yet documented).dist
directory, including the type definitions and source maps.The package is now published in ESM format. That could be considered a breaking change. I personally believe everyone should push to modern web standards and use ESM, but that is only my personal opinion. I could revert this, allthough Vitest should be able to handle ESM (actually, it embraces ESM).Never mind, it was already being published in ESM format before.