Skip to content

Commit 5500228

Browse files
committed
feat: implement waitFor option
1 parent a78aa19 commit 5500228

File tree

3 files changed

+39
-2
lines changed

3 files changed

+39
-2
lines changed

packages/fetch-mock/src/Route.ts

+23-1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ export type UserRouteSpecificConfig = {
3131
response?: RouteResponse | RouteResponseFunction;
3232
repeat?: number;
3333
delay?: number;
34+
waitFor?: RouteName;
3435
sticky?: boolean;
3536
};
3637
export type InternalRouteConfig = {
@@ -122,13 +123,15 @@ e.g. {"body": {"status: "registered"}}`);
122123
class Route {
123124
config: RouteConfig;
124125
matcher: RouteMatcherFunction;
126+
#responseSubscriptions: Array<() => void>;
125127

126128
constructor(config: RouteConfig) {
127129
this.init(config);
128130
}
129131

130132
init(config: RouteConfig | ModifyRouteConfig) {
131133
this.config = config;
134+
this.#responseSubscriptions = [];
132135
this.#sanitize();
133136
this.#validate();
134137
this.#generateMatcher();
@@ -197,6 +200,21 @@ class Route {
197200
}
198201
}
199202

203+
waitFor(awaitedRoute: Route) {
204+
const { response } = this.config;
205+
this.config.response = () => {
206+
return new Promise((res) =>
207+
awaitedRoute.onRespond(() => {
208+
res(response);
209+
}),
210+
);
211+
};
212+
}
213+
214+
onRespond(func: () => void) {
215+
this.#responseSubscriptions.push(func);
216+
}
217+
200218
constructResponse(responseInput: RouteResponseConfig): {
201219
response: Response;
202220
responseOptions: ResponseInit;
@@ -205,11 +223,15 @@ class Route {
205223
const responseOptions = this.constructResponseOptions(responseInput);
206224
const body = this.constructResponseBody(responseInput, responseOptions);
207225

208-
return {
226+
const responsePackage = {
209227
response: new this.config.Response(body, responseOptions),
210228
responseOptions,
211229
responseInput,
212230
};
231+
232+
this.#responseSubscriptions.forEach((func) => func());
233+
234+
return responsePackage;
213235
}
214236

215237
constructResponseOptions(

packages/fetch-mock/src/Router.ts

+15
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,21 @@ export default class Router {
342342
'fetch-mock: Adding route with same name as existing route.',
343343
);
344344
}
345+
if (route.config.waitFor) {
346+
const routeToAwait = this.routes.find(
347+
({ config: { name: existingName } }) =>
348+
route.config.waitFor === existingName,
349+
);
350+
351+
if (!routeToAwait) {
352+
throw new Error(
353+
`Cannot wait for route \`${route.config.waitFor}\`: route of that name does not exist`,
354+
);
355+
} else {
356+
route.waitFor(routeToAwait);
357+
}
358+
}
359+
345360
this.routes.push(route);
346361
}
347362
setFallback(response?: RouteResponse) {

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ describe('response negotiation', () => {
119119
describe('waitFor', () => {
120120
it('Error informatively if route to wait for does not exist', () => {
121121
expect(() => fm.route('*', 200, { waitFor: 'huh' })).toThrow(
122-
'no way on your nelly',
122+
'Cannot wait for route `huh`: route of that name does not exist',
123123
);
124124
});
125125
it('Not respond until waited for route responds', async () => {

0 commit comments

Comments
 (0)