Skip to content

Commit

Permalink
Merge pull request #719 from wheresrhys/rhys/no-top-level-done
Browse files Browse the repository at this point in the history
Rhys/no top level done
  • Loading branch information
wheresrhys authored Jul 20, 2024
2 parents 74ab8cc + 87206e6 commit 7676749
Show file tree
Hide file tree
Showing 7 changed files with 60 additions and 77 deletions.
6 changes: 1 addition & 5 deletions docs/docs/@fetch-mock/core/CallHistory.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,7 @@ Returns a Boolean indicating whether any calls to `fetch` matched the given `fil

Returns the `CallLog` for the last call to `fetch` matching the given `filter` and `options`.

### fetchMock.done(routeNames)

_Note that this function is exposed on the `fetchMock` object, not on `fetchMock.callHistory`_

TODO, should callHistory just have access to `routes`... yes probably as these docs are horrible
### .done(routeNames)

Returns a Boolean indicating whether `fetch` was called the expected number of times (or has been called at least once if `repeat` is not defined for the route). It does not take into account whether the `fetches` completed successfully.

Expand Down
2 changes: 1 addition & 1 deletion docs/docs/@fetch-mock/core/route/matcher.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ Match only requests that have these query parameters set (in any order). Query p

Match only requests that send a JSON body with the exact structure and properties as the one provided here.

Note that if matching on body _and_ using `Request` instances in your source code, this forces fetch-mock into an asynchronous flow _before_ it is able to route requests effectively. This means no [inspection methods](#api-inspectionfundamentals) can be used synchronously. You must first either await the fetches to resolve, or `await fetchMock.flush()`. The popular library [Ky](https://github.com/sindresorhus/ky) uses `Request` instances internally, and so also triggers this mode.
Note that if matching on body _and_ using `Request` instances in your source code, this forces fetch-mock into an asynchronous flow _before_ it is able to route requests effectively. This means no [inspection methods](#api-inspectionfundamentals) can be used synchronously. You must first either await the fetches to resolve, or `await fetchMock.callHistory.flush()`. The popular library [Ky](https://github.com/sindresorhus/ky) uses `Request` instances internally, and so also triggers this mode.

e.g.`{body: { "key1": "value1", "key2": "value2" }}`

Expand Down
22 changes: 13 additions & 9 deletions packages/core/src/CallHistory.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,13 @@ const isMatchedOrUnmatched = (filter) =>
class CallHistory {
/**
* @param {FetchMockConfig} globalConfig
* @param router
*/
constructor(globalConfig) {
constructor(globalConfig, router) {
/** @type {CallLog[]} */
this.callLogs = [];
this.config = globalConfig;
this.router = router;
}
/**
*
Expand Down Expand Up @@ -163,17 +165,19 @@ class CallHistory {
lastCall(filter, options) {
return this.calls(filter, options).pop();
}

/**
*
* @param {RouteName[]} [routeNames]
* @param {Route[]} allRoutes
* @param {RouteName|RouteName[]} [routeNames]
* @returns {boolean}
*/
done(allRoutes, routeNames) {
const routesToCheck = routeNames
? allRoutes.filter(({ config: { name } }) => routeNames.includes(name))
: allRoutes;

done(routeNames) {
let routesToCheck = this.router.routes;
if (routeNames) {
routeNames = Array.isArray(routeNames) ? routeNames : [routeNames];
routesToCheck = this.router.routes.filter(({ config: { name } }) =>
routeNames.includes(name),
);
}
// TODO when checking all routes needs to check against all calls
// Can't use array.every because would exit after first failure, which would
// break the logging
Expand Down
21 changes: 2 additions & 19 deletions packages/core/src/FetchMock.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,15 @@ const defaultConfig = {
const FetchMock = {
config: defaultConfig,
router: new Router(defaultConfig),
callHistory: new CallHistory(defaultConfig),
callHistory: new CallHistory(defaultConfig, this.router),
createInstance() {
const instance = Object.create(FetchMock);
instance.config = { ...this.config };
instance.router = new Router(instance.config, {
routes: [...this.router.routes],
fallbackRoute: this.router.fallbackRoute,
});
instance.callHistory = new CallHistory(this.config);
instance.callHistory = new CallHistory(instance.config, instance.router);
return instance;
},
/**
Expand Down Expand Up @@ -122,23 +122,6 @@ const FetchMock = {
defineMatcher(matcher) {
Route.defineMatcher(matcher);
},
flush(waitForResponseBody) {
return this.callHistory.flush(waitForResponseBody);
},
/**
*
* @param {RouteName|RouteName[]} routeNames
* @returns {boolean}
*/
done(routeNames) {
if (!routeNames) {
return this.callHistory.done(this.router.routes);
}
return this.callHistory.done(
this.router.routes,
Array.isArray(routeNames) ? routeNames : [routeNames],
);
},
removeRoutes(options) {
this.router.removeRoutes(options);
return this;
Expand Down
62 changes: 31 additions & 31 deletions packages/core/src/__tests__/CallHistory.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -362,11 +362,11 @@ describe('CallHistory', () => {
it('clearHistory() resets count done-ness', async () => {
fm = fetchMock.createInstance().route('http://a.com/', 200);
await fm.fetchHandler('http://a.com/');
expect(fm.done()).toBe(true);
expect(fm.callHistory.done()).toBe(true);
fm.clearHistory();
expect(fm.done()).toBe(false);
expect(fm.callHistory.done()).toBe(false);
await fm.fetchHandler('http://a.com/');
expect(fm.done()).toBe(true);
expect(fm.callHistory.done()).toBe(true);
});

describe('where number of expected calls is not specified', () => {
Expand All @@ -379,32 +379,32 @@ describe('CallHistory', () => {
});

it('can expect at least one call to have been made to every defined route', () => {
expect(fm.done()).toBe(false);
expect(fm.callHistory.done()).toBe(false);
fm.fetchHandler('http://a.com/');
expect(fm.done()).toBe(false);
expect(fm.callHistory.done()).toBe(false);
fm.fetchHandler('http://b.com/');
expect(fm.done()).toBe(false);
expect(fm.callHistory.done()).toBe(false);
fm.fetchHandler('http://c.com/');
expect(fm.done()).toBe(true);
expect(fm.callHistory.done()).toBe(true);
});

it('can expect a named route to be called at least once', () => {
expect(fm.done('a')).toBe(false);
expect(fm.done('b')).toBe(false);
expect(fm.callHistory.done('a')).toBe(false);
expect(fm.callHistory.done('b')).toBe(false);
fm.fetchHandler('http://a.com/');
expect(fm.done('a')).toBe(true);
expect(fm.done('b')).toBe(false);
expect(fm.callHistory.done('a')).toBe(true);
expect(fm.callHistory.done('b')).toBe(false);
fm.fetchHandler('http://a.com/');
expect(fm.done('a')).toBe(true);
expect(fm.done('b')).toBe(false);
expect(fm.callHistory.done('a')).toBe(true);
expect(fm.callHistory.done('b')).toBe(false);
});

it('can expect multiple named routes to be called at least once each', () => {
expect(fm.done(['a', 'b'])).toBe(false);
expect(fm.callHistory.done(['a', 'b'])).toBe(false);
fm.fetchHandler('http://a.com/');
expect(fm.done(['a', 'b'])).toBe(false);
expect(fm.callHistory.done(['a', 'b'])).toBe(false);
fm.fetchHandler('http://b.com/');
expect(fm.done(['a', 'b'])).toBe(true);
expect(fm.callHistory.done(['a', 'b'])).toBe(true);
});
});
describe('where number of expected calls is specified', () => {
Expand All @@ -417,32 +417,32 @@ describe('CallHistory', () => {
});

it('can expect a named route to be called specified number of times', () => {
expect(fm.done('a')).toBe(false);
expect(fm.callHistory.done('a')).toBe(false);
fm.fetchHandler('http://a.com/');
expect(fm.done('a')).toBe(false);
expect(fm.callHistory.done('a')).toBe(false);
fm.fetchHandler('http://a.com/');
expect(fm.done('a')).toBe(true);
expect(fm.callHistory.done('a')).toBe(true);
});

it('can expect multiple named routes to be called specified number of times', () => {
expect(fm.done(['a', 'b'])).toBe(false);
expect(fm.callHistory.done(['a', 'b'])).toBe(false);
fm.fetchHandler('http://a.com/');
fm.fetchHandler('http://b.com/');
expect(fm.done(['a', 'b'])).toBe(false);
expect(fm.callHistory.done(['a', 'b'])).toBe(false);
fm.fetchHandler('http://a.com/');
expect(fm.done(['a', 'b'])).toBe(true);
expect(fm.callHistory.done(['a', 'b'])).toBe(true);
});

it('can expect specific number of calls to have been made to every defined route', () => {
expect(fm.done()).toBe(false);
expect(fm.callHistory.done()).toBe(false);
fm.fetchHandler('http://a.com/');
fm.fetchHandler('http://b.com/');
fm.fetchHandler('http://c.com/');
expect(fm.done()).toBe(false);
expect(fm.callHistory.done()).toBe(false);
fm.fetchHandler('http://a.com/');
expect(fm.done()).toBe(false);
expect(fm.callHistory.done()).toBe(false);
fm.fetchHandler('http://c.com/');
expect(fm.done()).toBe(true);
expect(fm.callHistory.done()).toBe(true);
});

it('can combine with routes where specific number of calls is unspecified', () => {
Expand All @@ -452,15 +452,15 @@ describe('CallHistory', () => {
.route('http://b.com/', 200, { name: 'b' })
.route('http://c.com/', 200);

expect(fm.done()).toBe(false);
expect(fm.callHistory.done()).toBe(false);
fm.fetchHandler('http://a.com/');
fm.fetchHandler('http://b.com/');
fm.fetchHandler('http://c.com/');
expect(fm.done()).toBe(false);
expect(fm.done(['a', 'b'])).toBe(false);
expect(fm.callHistory.done()).toBe(false);
expect(fm.callHistory.done(['a', 'b'])).toBe(false);
fm.fetchHandler('http://a.com/');
expect(fm.done()).toBe(true);
expect(fm.done(['a', 'b'])).toBe(true);
expect(fm.callHistory.done()).toBe(true);
expect(fm.callHistory.done(['a', 'b'])).toBe(true);
});
});
});
Expand Down
18 changes: 9 additions & 9 deletions packages/core/src/__tests__/FetchMock/flush.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ describe('FetchMockWrapper.js', () => {
fm.route('http://one.com/', 200).route('http://two.com/', 200);
// no expectation, but if it doesn't work then the promises will hang
// or reject and the test will timeout
await fm.flush();
await fm.callHistory.flush();
fm.fetchHandler('http://one.com');
await fm.flush();
await fm.callHistory.flush();
fm.fetchHandler('http://two.com');
await fm.flush();
await fm.callHistory.flush();
});

it('should resolve after fetches', async () => {
Expand All @@ -25,7 +25,7 @@ describe('FetchMockWrapper.js', () => {
fm.fetchHandler('http://example').then(() => {
data = 'done';
});
await fm.flush();
await fm.callHistory.flush();
expect(data).toEqual('done');
});

Expand All @@ -38,7 +38,7 @@ describe('FetchMockWrapper.js', () => {
data = 'done';
});

await fm.flush(true);
await fm.callHistory.flush(true);
expect(data).toEqual('done');
});
it('should resolve after .json() if waitForResponseMethods option passed', async () => {
Expand All @@ -50,7 +50,7 @@ describe('FetchMockWrapper.js', () => {
data = 'done';
});

await fm.flush(true);
await fm.callHistory.flush(true);
expect(data).toEqual('done');
});

Expand All @@ -63,7 +63,7 @@ describe('FetchMockWrapper.js', () => {
data = 'done';
});

await fm.flush(true);
await fm.callHistory.flush(true);
expect(data).toEqual('done');
});
});
Expand All @@ -80,14 +80,14 @@ describe('FetchMockWrapper.js', () => {

setTimeout(() => orderedResults.push('not flush'), 25);

await fm.flush();
await fm.callHistory.flush();
orderedResults.push('flush');
expect(orderedResults).toEqual(['not flush', 'flush']);
});

it('flush resolves on expected error', async () => {
fm.route('http://one.com/', { throws: 'Problem in space' });
await fm.flush();
await fm.callHistory.flush();
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ describe('response negotiation', () => {
await expectAbortError('http://a.com', {
signal: getDelayedAbortController().signal,
});
expect(fm.done()).toBe(true);
expect(fm.callHistory.done()).toBe(true);
});

it('will flush even when aborted', async () => {
Expand All @@ -218,8 +218,8 @@ describe('response negotiation', () => {
await expectAbortError('http://a.com', {
signal: getDelayedAbortController().signal,
});
await fm.flush();
expect(fm.done()).toBe(true);
await fm.callHistory.flush();
expect(fm.callHistory.done()).toBe(true);
});
});
});

0 comments on commit 7676749

Please sign in to comment.