Skip to content

Commit c3dc9c3

Browse files
committed
feat: add ability to wait for multiple routes
1 parent 8783101 commit c3dc9c3

File tree

4 files changed

+59
-19
lines changed

4 files changed

+59
-19
lines changed

docs/docs/API/route/options.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ Delays responding for the number of milliseconds specified.
3232

3333
### waitFor
3434

35-
`{String}`
36-
Useful for testing race conditions. Use the name of another route, and this route will only respond after that one has. (Note, this does not wait for the body - only the initial response payload).
35+
`{String|[String]}`
36+
Useful for testing race conditions. Use the name of another route (or a list of names), and this route will only respond after that one has. (Note, this does not wait for the body - only the initial response payload).
3737

3838
### sticky
3939

packages/fetch-mock/src/Route.ts

+12-7
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export type UserRouteSpecificConfig = {
3131
response?: RouteResponse | RouteResponseFunction;
3232
repeat?: number;
3333
delay?: number;
34-
waitFor?: RouteName;
34+
waitFor?: RouteName | RouteName[];
3535
sticky?: boolean;
3636
};
3737
export type InternalRouteConfig = {
@@ -200,13 +200,18 @@ class Route {
200200
}
201201
}
202202

203-
waitFor(awaitedRoute: Route) {
203+
waitFor(awaitedRoutes: Route[]) {
204204
const { response } = this.config;
205-
this.config.response = new Promise((res) =>
206-
awaitedRoute.onRespond(() => {
207-
res(response);
208-
}),
209-
);
205+
this.config.response = Promise.all(
206+
awaitedRoutes.map(
207+
(awaitedRoute) =>
208+
new Promise((res) =>
209+
awaitedRoute.onRespond(() => {
210+
res(undefined);
211+
}),
212+
),
213+
),
214+
).then(() => response);
210215
}
211216

212217
onRespond(func: () => void) {

packages/fetch-mock/src/Router.ts

+19-10
Original file line numberDiff line numberDiff line change
@@ -343,18 +343,27 @@ export default class Router {
343343
);
344344
}
345345
if (route.config.waitFor) {
346-
const routeToAwait = this.routes.find(
347-
({ config: { name: existingName } }) =>
348-
route.config.waitFor === existingName,
349-
);
346+
const routeNamesToWaitFor = Array.isArray(route.config.waitFor)
347+
? route.config.waitFor
348+
: [route.config.waitFor];
349+
350+
const routesToAwait: Route[] = [];
350351

351-
if (!routeToAwait) {
352-
throw new Error(
353-
`Cannot wait for route \`${route.config.waitFor}\`: route of that name does not exist`,
352+
routeNamesToWaitFor.forEach((routeName) => {
353+
const routeToAwait = this.routes.find(
354+
({ config: { name: existingName } }) => routeName === existingName,
354355
);
355-
} else {
356-
route.waitFor(routeToAwait);
357-
}
356+
357+
if (routeToAwait) {
358+
routesToAwait.push(routeToAwait);
359+
} else {
360+
throw new Error(
361+
`Cannot wait for route \`${routeName}\`: route of that name does not exist`,
362+
);
363+
}
364+
});
365+
366+
route.waitFor(routesToAwait);
358367
}
359368

360369
this.routes.push(route);

packages/fetch-mock/src/__tests__/FetchMock/response-negotiation.test.js

+26
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,32 @@ describe('response negotiation', () => {
157157
]);
158158
expect(routesCalled).toEqual(['a', 'b', 'c']);
159159
});
160+
161+
it('Can wait for multiple routes', async () => {
162+
fm.route('http://a.com', 200, 'route-a')
163+
.route('http://b.com', 200, 'route-b')
164+
.route('http://c.com', 200, { waitFor: ['route-a', 'route-b'] });
165+
let routesCalled = [];
166+
await Promise.all([
167+
fm.fetchHandler('http://c.com').then(() => routesCalled.push('c')),
168+
fm.fetchHandler('http://b.com').then(() => routesCalled.push('b')),
169+
fm.fetchHandler('http://a.com').then(() => routesCalled.push('a')),
170+
]);
171+
expect(routesCalled).toEqual(['b', 'a', 'c']);
172+
});
173+
174+
it('Not error if waited for route responds again', async () => {
175+
fm.route('http://a.com', 200, 'route-a').route('http://b.com', 200, {
176+
waitFor: 'route-a',
177+
});
178+
await Promise.all([
179+
fm.fetchHandler('http://b.com'),
180+
fm.fetchHandler('http://a.com'),
181+
]);
182+
await expect(fm.fetchHandler('http://a.com')).resolves.toBeInstanceOf(
183+
Response,
184+
);
185+
});
160186
});
161187
it('Response', async () => {
162188
fm.route('http://a.com/', new Response('http://a.com/', { status: 200 }));

0 commit comments

Comments
 (0)