Skip to content

Commit

Permalink
Expose .calls with normalizeRequest (#8)
Browse files Browse the repository at this point in the history
* Add safer alternative to .calls

* Fix handling of aborted requests

* Add missing return
(I forgor)

* Remove vscode settings file

* Improve documentation
  • Loading branch information
stefnotch authored Feb 16, 2023
1 parent 8574911 commit ef6f09c
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 12 deletions.
26 changes: 14 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -273,8 +273,8 @@ describe('testing api', () => {
expect(res.data).toEqual('12345');

//assert on the times called and arguments given to fetch
expect(fetch.mock.calls.length).toEqual(1);
expect(fetch.mock.calls[0][0]).toEqual('https://google.com');
expect(fetch.requests().length).toEqual(1);
expect(fetch.requests()[0].url).toEqual('https://google.com/');
});
});
```
Expand Down Expand Up @@ -613,12 +613,13 @@ describe('getYear action creator', () => {

### Using `fetch.mock` to inspect the mock state of each fetch call

`fetch.mock` by default uses [Vitest's mocking functions](https://vitest.dev/api/#mockinstance-properties). Therefore
`fetch.mock` by default uses [Vitest's mocking functions](https://vitest.dev/api/mock.html). Therefore
you can make assertions on the mock state. In this example we have an arbitrary function that makes a different fetch
request based on the argument you pass to it. In our test, we run Vitest's `beforeEach()` and make sure to reset our
mock before each `it()` block as we will make assertions on the arguments we are passing to `fetch()`. The most uses
property is the `fetch.mock.calls` array. It can give you information on each call, and their arguments which you can
use for your `expect()` calls. Vitest also comes with some nice aliases for the most used ones.
mock before each `it()` block as we will make assertions on the arguments we are passing to `fetch()`. Then we use the
`fetch.requests()` function to give us a history of all non-aborted requests (normalized) that were made. It can give you
information on each call, and their arguments which you can use for your `expect()` calls. Vitest also comes with some
nice aliases for the most used ones.

```js
// api.js
Expand Down Expand Up @@ -649,25 +650,26 @@ describe('testing api', () => {
fetch.mockResponse(JSON.stringify({ secret_data: '12345' }));
APIRequest();

expect(fetch.mock.calls.length).toEqual(1);
expect(fetch.mock.calls[0][0]).toEqual('https://google.com');
// there was one request, which was not aborted
expect(fetch.requests().length).toEqual(1);
expect(fetch.requests()[0].url).toEqual('https://google.com/');
});

it('calls facebook', () => {
fetch.mockResponse(JSON.stringify({ secret_data: '12345' }));
APIRequest('facebook');

expect(fetch.mock.calls.length).toEqual(2);
expect(fetch.mock.calls[0][0]).toEqual('https://facebook.com/someOtherResource');
expect(fetch.mock.calls[1][0]).toEqual('https://facebook.com');
expect(fetch.requests().length).toEqual(2);
expect(fetch.requests()[0].url).toEqual('https://facebook.com/someOtherResource');
expect(fetch.requests()[1].url).toEqual('https://facebook.com/');
});

it('calls twitter', () => {
fetch.mockResponse(JSON.stringify({ secret_data: '12345' }));
APIRequest('twitter');

expect(fetch).toBeCalled(); // alias for expect(fetch.mock.calls.length).toEqual(1);
expect(fetch).toBeCalledWith('https://twitter.com'); // alias for expect(fetch.mock.calls[0][0]).toEqual();
expect(fetch.requests().map(v => v.url)).toContain('https://twitter.com/');
});
});
```
Expand Down
13 changes: 13 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,19 @@ export default function createFetchMocker(vi) {
return fetch;
};

fetch.requests = () => {
const requests = [];
fetch.mock.calls.forEach((call) => {
try {
let req = normalizeRequest(call[0], call[1]);
requests.push(req);
} catch(e) {
// ignore
}
});
return requests;
};

fetch.resetMocks = () => {
fetch.mockReset();
isMocking.mockReset();
Expand Down
13 changes: 13 additions & 0 deletions tests/api.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ describe('testing mockResponse and alias once', () => {
expect(response).toEqual({ secret_data: 'abcde' });
expect(fetch.mock.calls.length).toEqual(1);
expect(fetch.mock.calls[0][0]).toEqual('https://google.com');
expect(fetch.requests().length).toEqual(1);
expect(fetch.requests()[0].url).toEqual('https://google.com/');
});

it('mocks a response with chaining', async () => {
Expand Down Expand Up @@ -53,6 +55,7 @@ describe('testing mockResponse and alias once', () => {
expect(fetch.mock.calls.length).toEqual(2);

expect(fetch.mock.calls[0][0]).toEqual('https://facebook.com/someOtherResource');
expect(fetch.requests()[0].url).toEqual('https://facebook.com/someOtherResource');
expect(fetch.mock.calls[1][0]).toEqual('https://facebook.com');
});

Expand All @@ -66,6 +69,16 @@ describe('testing mockResponse and alias once', () => {
expect(fetch.mock.calls[0][0]).toEqual(new URL('https://instagram.com'));
});

it('returns normalized requests', async () => {
fetch.mockResponseOnce(JSON.stringify({ secret_data: 'abcde' }, { status: 200 }));

const response = await APIRequest('instagram');

expect(response).toEqual({ secret_data: 'abcde' });
expect(fetch.requests().length).toEqual(1);
expect(fetch.requests()[0].method).toEqual("GET");
});

it('supports an object with a stringifier', async () => {
fetch.mockResponseOnce(JSON.stringify({ secret_data: 'abcde' }, { status: 200 }));

Expand Down
6 changes: 6 additions & 0 deletions types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,12 @@ export interface FetchMock

dontMockOnceIf(urlOrPredicate: UrlOrPredicate, fn?: MockResponseInitFunction): FetchMock;
dontMockOnceIf(urlOrPredicate: UrlOrPredicate, response: string, responseInit?: MockParams): FetchMock;

/**
* Returns all the requests that have been made to the mocked fetch function.
* Does not include aborted requests.
*/
requests(): Request[];

resetMocks(): void;
enableMocks(): void;
Expand Down

0 comments on commit ef6f09c

Please sign in to comment.