Skip to content

Commit

Permalink
Merge pull request #867 from wheresrhys/rhys/relative-url-matching
Browse files Browse the repository at this point in the history
Rhys/relative url matching
  • Loading branch information
wheresrhys authored Nov 8, 2024
2 parents 225a0ea + e1bbcad commit f51fc04
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 6 deletions.
18 changes: 13 additions & 5 deletions docs/docs/Usage/upgrade-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,27 @@ The [@fetch-mock/codemods](https://www.npmjs.com/package/@fetch-mock/codemods) l

## Summary of changes

### Uses global, native `fetch` implementation in all environments

Previously this was true in browsers, but in node.js the node-fetch library was used.

### `.mock()` method removed

This combined adding a route with mocking the global instance of `fetch`. These are now split into 2 methods: `.route()` and `.mockGlobal()`.

## Reset methods changed
### Reset methods changed

`.reset()`, `.restore()`, `.resetBehavior()` and `.resetHistory()` have been removed and replaced with [methods that are more granular and clearly named](/fetch-mock/docs/API/resetting). Note that the [jest](/fetch-mock/docs/wrappers/jest) and [vitest](/fetch-mock/docs/wrappers/vitest) wrappers for fetch-mock still implement `.mockClear()`, `mockReset()` and `mockRestore()`.

## Call history methods changed
### Call history methods changed

The filtering behaviour has been rewritten around named routes, and methods return CallLog objects that contain far more metadata about the call. [Call history docs](/fetch-mock/docs/API/CallHistory)

## Some convenience routing methods removed
### Relative URLs not permitted by default in Node.js

A consequence of shifting to use the native implementation of the URL class is that relative URLs are no longer permissable when running tests in node.js, but [this can easily be enabled](https://www.wheresrhys.co.uk/fetch-mock/docs/Usage/configuration#allowrelativeurls).

### Some convenience routing methods removed

`getOnce()` and `getAnyOnce()` have been removed, but the behaviour can still be implemented by the user as follows:

Expand All @@ -29,13 +37,13 @@ The filtering behaviour has been rewritten around named routes, and methods retu

The same is true for `postOnce()`, `deleteOnce()` etc.

## Options removed
### Options removed

- `overwriteRoutes` - this reflects that multiple routes using the same underlying matcher but different options no longer throw an error.
- `warnOnFallback` - given the improved state of node.js debugging tools compared to when fetch-mock was first written, this debugging utilty has been removed.
- `sendAsJson` - fetch-mock@12 implements streams more robustly than previous options, so the user no longer needs to flag when an object response should be converted to JSON.
- `fallbackToNetwork` - The [`spyGlobal()` method](/fetch-mock/docs/API/mocking-and-spying#spyglobal) should now be used.

## `sandbox()` method removed
### `sandbox()` method removed

This was principally used when mocking node-fetch referenced as a local variable. Given that `fetch` is now available as a native global it's less useful and has been removed. If necessary to mock a local instance of node-fetch use [`.fetchHandler`](/fetch-mock/docs/API/mocking-and-spying#fetchhandler)
2 changes: 1 addition & 1 deletion packages/fetch-mock/src/RequestUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export type NormalizedRequestOptions =
export function hasCredentialsInUrl(url: string): boolean {
const urlObject = new URL(
url,
protocolRelativeUrlRX.test(url) ? 'http://dummy' : undefined,
!absoluteUrlRX.test(url) ? 'http://dummy' : undefined,
);
return Boolean(urlObject.username || urlObject.password);
}
Expand Down
9 changes: 9 additions & 0 deletions packages/fetch-mock/src/__tests__/router-integration.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { describe, expect, it } from 'vitest';
import fetchMock from '../FetchMock';
describe('router integration', () => {
const isBrowser = Boolean(globalThis.location);
it('matchurls when called with Request', async () => {
const fm = fetchMock.createInstance();
fm.post('http://a.com/', 200).catch();
Expand Down Expand Up @@ -65,6 +66,14 @@ describe('router integration', () => {
),
).resolves.not.toThrow();
});
if (!isBrowser) {
it('can match relative urls when allowRelativeUrls option is true', async () => {
const fm = fetchMock.createInstance();
fm.route('/path', 200, { allowRelativeUrls: true });
const res = await fm.fetchHandler('/path');
expect(res.status).toEqual(200);
});
}
});
describe('user defined matchers', () => {
it('match on sync property', async () => {
Expand Down
9 changes: 9 additions & 0 deletions packages/fetch-mock/src/__tests__/spec-compliance.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,15 @@ describe('Spec compliance', () => {
),
);
});
it('rejects on protocol agnostic url containing credentials', async () => {
await expect(
fetchMock.fetchHandler('//user:[email protected]'),
).rejects.toThrow(
new TypeError(
'Request cannot be constructed from a URL that includes credentials: //user:[email protected]/',
),
);
});
it('reject if the request method is GET or HEAD and the body is non-null.', async () => {
await expect(
fetchMock.fetchHandler('http://a.com', { body: 'a' }),
Expand Down

0 comments on commit f51fc04

Please sign in to comment.