From 991a7b41f817aeed223663e28ac6cf894b85cf2b Mon Sep 17 00:00:00 2001 From: Artem Zakharchenko Date: Mon, 25 Mar 2024 12:58:04 +0100 Subject: [PATCH 01/12] test: add generator resolver tests --- test/node/rest-api/response/generator.test.ts | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 test/node/rest-api/response/generator.test.ts diff --git a/test/node/rest-api/response/generator.test.ts b/test/node/rest-api/response/generator.test.ts new file mode 100644 index 000000000..6781ecdcb --- /dev/null +++ b/test/node/rest-api/response/generator.test.ts @@ -0,0 +1,62 @@ +/** + * @vitest-environment node + */ +import { http, HttpResponse, delay } from 'msw' +import { setupServer } from 'msw/node' + +const server = setupServer() +const toJson = (response: Response) => response.json() + +beforeAll(() => { + server.listen() +}) + +afterEach(() => { + server.resetHandlers() +}) + +afterAll(() => { + server.close() +}) + +it('supports generator function as response resolver', async () => { + server.use( + http.get('https://example.com/weather', function* () { + let degree = 10 + + if (degree < 12) { + degree++ + yield HttpResponse.json(degree) + } + + return HttpResponse.json(degree) + }), + ) + + expect(await fetch('https://example.com/weather').then(toJson)).toEqual(11) + expect(await fetch('https://example.com/weather').then(toJson)).toEqual(12) + expect(await fetch('https://example.com/weather').then(toJson)).toEqual(13) + expect(await fetch('https://example.com/weather').then(toJson)).toEqual(13) +}) + +it('supports async generator function as response resolver', async () => { + server.use( + http.get('https://example.com/weather', async function* () { + await delay(20) + + let degree = 10 + + if (degree < 12) { + degree++ + yield HttpResponse.json(degree) + } + + return HttpResponse.json(degree) + }), + ) + + expect(await fetch('https://example.com/weather').then(toJson)).toEqual(11) + expect(await fetch('https://example.com/weather').then(toJson)).toEqual(12) + expect(await fetch('https://example.com/weather').then(toJson)).toEqual(13) + expect(await fetch('https://example.com/weather').then(toJson)).toEqual(13) +}) From f324d339fe044446df53202673b1c7508b137e4b Mon Sep 17 00:00:00 2001 From: Artem Zakharchenko Date: Mon, 25 Mar 2024 13:46:58 +0100 Subject: [PATCH 02/12] fix: support async generator response resolvers --- src/core/handlers/RequestHandler.ts | 61 ++++++++----------- src/core/utils/internal/isIterable.ts | 8 ++- test/node/rest-api/response/generator.test.ts | 50 ++++++++++++++- 3 files changed, 79 insertions(+), 40 deletions(-) diff --git a/src/core/handlers/RequestHandler.ts b/src/core/handlers/RequestHandler.ts index 5c0c3ffa7..8cff2bcb4 100644 --- a/src/core/handlers/RequestHandler.ts +++ b/src/core/handlers/RequestHandler.ts @@ -1,4 +1,3 @@ -import { invariant } from 'outvariant' import { getCallFrame } from '../utils/internal/getCallFrame' import { isIterable } from '../utils/internal/isIterable' import type { ResponseResolutionContext } from '../utils/executeHandlers' @@ -117,11 +116,17 @@ export abstract class RequestHandler< public isUsed: boolean protected resolver: ResponseResolver - private resolverGenerator?: Generator< - MaybeAsyncResponseResolverReturnType, - MaybeAsyncResponseResolverReturnType, - MaybeAsyncResponseResolverReturnType - > + private resolverGenerator?: + | Generator< + MaybeAsyncResponseResolverReturnType, + MaybeAsyncResponseResolverReturnType, + MaybeAsyncResponseResolverReturnType + > + | AsyncGenerator< + MaybeAsyncResponseResolverReturnType, + MaybeAsyncResponseResolverReturnType, + MaybeAsyncResponseResolverReturnType + > private resolverGeneratorResult?: Response | StrictResponse private options?: HandlerOptions @@ -256,8 +261,6 @@ export abstract class RequestHandler< return null } - this.isUsed = true - // Create a response extraction wrapper around the resolver // since it can be both an async function and a generator. const executeResolver = this.wrapResolver(this.resolver) @@ -304,44 +307,32 @@ export abstract class RequestHandler< const result = this.resolverGenerator || (await resolver(info)) if (isIterable>(result)) { - // Immediately mark this handler as unused. - // Only when the generator is done, the handler will be - // considered used. - this.isUsed = false + if (!this.resolverGenerator) { + this.resolverGenerator = result + } - const { value, done } = result[Symbol.iterator]().next() + const { done, value } = await this.resolverGenerator.next() const nextResponse = await value - if (done) { - this.isUsed = true - } - - // If the generator is done and there is no next value, - // return the previous generator's value. - if (!nextResponse && done) { - invariant( - this.resolverGeneratorResult, - 'Failed to returned a previously stored generator response: the value is not a valid Response.', - ) - - // Clone the previously stored response from the generator - // so that it could be read again. - return this.resolverGeneratorResult.clone() as StrictResponse + if (nextResponse) { + this.resolverGeneratorResult = nextResponse.clone() } - if (!this.resolverGenerator) { - this.resolverGenerator = result - } + if (done) { + // A one-time generator resolver stops affecting the network + // only after it's been completely exhausted. + this.isUsed = true - if (nextResponse) { - // Also clone the response before storing it - // so it could be read again. - this.resolverGeneratorResult = nextResponse?.clone() + // Clone the previously stored response so it can be read + // when receiving it repeatedly from the "done" generator. + return this.resolverGeneratorResult?.clone() } return nextResponse } + // Regular one-time resolver is marked as used immediately. + this.isUsed = true return result } } diff --git a/src/core/utils/internal/isIterable.ts b/src/core/utils/internal/isIterable.ts index c3ef63783..c371158ed 100644 --- a/src/core/utils/internal/isIterable.ts +++ b/src/core/utils/internal/isIterable.ts @@ -3,10 +3,14 @@ */ export function isIterable( fn: any, -): fn is Generator { +): fn is + | Generator + | AsyncGenerator { if (!fn) { return false } - return typeof (fn as Generator)[Symbol.iterator] == 'function' + return ( + Reflect.has(fn, Symbol.iterator) || Reflect.has(fn, Symbol.asyncIterator) + ) } diff --git a/test/node/rest-api/response/generator.test.ts b/test/node/rest-api/response/generator.test.ts index 6781ecdcb..15fb6905a 100644 --- a/test/node/rest-api/response/generator.test.ts +++ b/test/node/rest-api/response/generator.test.ts @@ -24,19 +24,24 @@ it('supports generator function as response resolver', async () => { http.get('https://example.com/weather', function* () { let degree = 10 - if (degree < 12) { + while (degree < 13) { degree++ yield HttpResponse.json(degree) } + degree++ return HttpResponse.json(degree) }), ) + // Must respond with yielded responses. expect(await fetch('https://example.com/weather').then(toJson)).toEqual(11) expect(await fetch('https://example.com/weather').then(toJson)).toEqual(12) expect(await fetch('https://example.com/weather').then(toJson)).toEqual(13) - expect(await fetch('https://example.com/weather').then(toJson)).toEqual(13) + // Must respond with the final "done" response. + expect(await fetch('https://example.com/weather').then(toJson)).toEqual(14) + // Must keep responding with the final "done" response. + expect(await fetch('https://example.com/weather').then(toJson)).toEqual(14) }) it('supports async generator function as response resolver', async () => { @@ -46,11 +51,12 @@ it('supports async generator function as response resolver', async () => { let degree = 10 - if (degree < 12) { + while (degree < 13) { degree++ yield HttpResponse.json(degree) } + degree++ return HttpResponse.json(degree) }), ) @@ -58,5 +64,43 @@ it('supports async generator function as response resolver', async () => { expect(await fetch('https://example.com/weather').then(toJson)).toEqual(11) expect(await fetch('https://example.com/weather').then(toJson)).toEqual(12) expect(await fetch('https://example.com/weather').then(toJson)).toEqual(13) + expect(await fetch('https://example.com/weather').then(toJson)).toEqual(14) + expect(await fetch('https://example.com/weather').then(toJson)).toEqual(14) +}) + +it('supports generator function as one-time response resolver', async () => { + server.use( + http.get( + 'https://example.com/weather', + function* () { + let degree = 10 + + while (degree < 13) { + degree++ + yield HttpResponse.json(degree) + } + + degree++ + return HttpResponse.json(degree) + }, + { once: true }, + ), + http.get('*', () => { + return HttpResponse.json('fallback') + }), + ) + + // Must respond with the yielded incrementing responses. + expect(await fetch('https://example.com/weather').then(toJson)).toEqual(11) + expect(await fetch('https://example.com/weather').then(toJson)).toEqual(12) expect(await fetch('https://example.com/weather').then(toJson)).toEqual(13) + // Must respond with the "done" final response from the iterator. + expect(await fetch('https://example.com/weather').then(toJson)).toEqual(14) + // Must respond with the other handler since the generator one is used. + expect(await fetch('https://example.com/weather').then(toJson)).toEqual( + 'fallback', + ) + expect(await fetch('https://example.com/weather').then(toJson)).toEqual( + 'fallback', + ) }) From baf112ec46ebb8062ae47670d1b25fe1f59e5223 Mon Sep 17 00:00:00 2001 From: Artem Zakharchenko Date: Mon, 25 Mar 2024 13:52:06 +0100 Subject: [PATCH 03/12] fix: accept AsyncGenerator as response resolver type --- src/core/handlers/RequestHandler.ts | 5 ++++ test/typings/resolver-generator.test-d.ts | 36 +++++++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 test/typings/resolver-generator.test-d.ts diff --git a/src/core/handlers/RequestHandler.ts b/src/core/handlers/RequestHandler.ts index 8cff2bcb4..5920ce67b 100644 --- a/src/core/handlers/RequestHandler.ts +++ b/src/core/handlers/RequestHandler.ts @@ -56,6 +56,11 @@ export type AsyncResponseResolverReturnType< MaybeAsyncResponseResolverReturnType, MaybeAsyncResponseResolverReturnType > + | AsyncGenerator< + MaybeAsyncResponseResolverReturnType, + MaybeAsyncResponseResolverReturnType, + MaybeAsyncResponseResolverReturnType + > > export type ResponseResolverInfo< diff --git a/test/typings/resolver-generator.test-d.ts b/test/typings/resolver-generator.test-d.ts new file mode 100644 index 000000000..438124558 --- /dev/null +++ b/test/typings/resolver-generator.test-d.ts @@ -0,0 +1,36 @@ +import { it } from 'vitest' +import { http, HttpResponse } from 'msw' + +it('supports generator function as response resolver', () => { + http.get('/', function* () { + yield HttpResponse.json({ value: 1 }) + yield HttpResponse.json({ value: 2 }) + return HttpResponse.json({ value: 3 }) + }) + + http.get('/', function* () { + yield HttpResponse.json({ value: 'one' }) + yield HttpResponse.json({ + // @ts-expect-error Expected string, got number. + value: 2, + }) + return HttpResponse.json({ value: 'three' }) + }) +}) + +it('supports async generator function as response resolver', () => { + http.get('/', async function* () { + yield HttpResponse.json({ value: 1 }) + yield HttpResponse.json({ value: 2 }) + return HttpResponse.json({ value: 3 }) + }) + + http.get('/', async function* () { + yield HttpResponse.json({ value: 'one' }) + yield HttpResponse.json({ + // @ts-expect-error Expected string, got number. + value: 2, + }) + return HttpResponse.json({ value: 'three' }) + }) +}) From 11d37194db31825517f4ac02bf1a76bfda2dbc2b Mon Sep 17 00:00:00 2001 From: Artem Zakharchenko Date: Mon, 25 Mar 2024 14:05:36 +0100 Subject: [PATCH 04/12] fix(RequestHandler): mark as used early, opt-out in generators --- src/core/handlers/RequestHandler.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/core/handlers/RequestHandler.ts b/src/core/handlers/RequestHandler.ts index 5920ce67b..ef5653cf2 100644 --- a/src/core/handlers/RequestHandler.ts +++ b/src/core/handlers/RequestHandler.ts @@ -266,6 +266,11 @@ export abstract class RequestHandler< return null } + // Preemptively mark the handler as used. + // Generators will undo this because only when the resolver reaches the + // "done" state of the generator that it considers the handler used. + this.isUsed = true + // Create a response extraction wrapper around the resolver // since it can be both an async function and a generator. const executeResolver = this.wrapResolver(this.resolver) @@ -312,6 +317,9 @@ export abstract class RequestHandler< const result = this.resolverGenerator || (await resolver(info)) if (isIterable>(result)) { + // Opt-out from marking this handler as used. + this.isUsed = false + if (!this.resolverGenerator) { this.resolverGenerator = result } @@ -336,8 +344,6 @@ export abstract class RequestHandler< return nextResponse } - // Regular one-time resolver is marked as used immediately. - this.isUsed = true return result } } From aac734a95296784d193d43cd980a8fac3a912336 Mon Sep 17 00:00:00 2001 From: Artem Zakharchenko Date: Mon, 25 Mar 2024 14:19:20 +0100 Subject: [PATCH 05/12] fix(RequestHandler): unwrap AsyncGenerator generic from MaybePromise --- src/core/handlers/RequestHandler.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/core/handlers/RequestHandler.ts b/src/core/handlers/RequestHandler.ts index ef5653cf2..b8bb9ca52 100644 --- a/src/core/handlers/RequestHandler.ts +++ b/src/core/handlers/RequestHandler.ts @@ -57,9 +57,9 @@ export type AsyncResponseResolverReturnType< MaybeAsyncResponseResolverReturnType > | AsyncGenerator< - MaybeAsyncResponseResolverReturnType, - MaybeAsyncResponseResolverReturnType, - MaybeAsyncResponseResolverReturnType + ResponseResolverReturnType, + ResponseResolverReturnType, + ResponseResolverReturnType > > From 8e26859f08ac85358e20470e3ea4bf765c5773d3 Mon Sep 17 00:00:00 2001 From: Artem Zakharchenko Date: Mon, 25 Mar 2024 14:22:49 +0100 Subject: [PATCH 06/12] test: add return type tests for generators --- test/typings/resolver-generator.test-d.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test/typings/resolver-generator.test-d.ts b/test/typings/resolver-generator.test-d.ts index 438124558..f69478ef1 100644 --- a/test/typings/resolver-generator.test-d.ts +++ b/test/typings/resolver-generator.test-d.ts @@ -34,3 +34,17 @@ it('supports async generator function as response resolver', () => { return HttpResponse.json({ value: 'three' }) }) }) + +it('supports returning nothing from generator resolvers', () => { + http.get('/', function* () {}) + http.get('/', async function* () {}) +}) + +it('supports returning undefined from generator resolvers', () => { + http.get('/', function* () { + return undefined + }) + http.get('/', async function* () { + return undefined + }) +}) From 180b722aef5d115392f6e6bb663e248cac2ea0bd Mon Sep 17 00:00:00 2001 From: Artem Zakharchenko Date: Mon, 25 Mar 2024 14:27:58 +0100 Subject: [PATCH 07/12] chore: revert MaybeAsync to AsyncGenerator generic --- src/core/handlers/RequestHandler.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/core/handlers/RequestHandler.ts b/src/core/handlers/RequestHandler.ts index b8bb9ca52..ef5653cf2 100644 --- a/src/core/handlers/RequestHandler.ts +++ b/src/core/handlers/RequestHandler.ts @@ -57,9 +57,9 @@ export type AsyncResponseResolverReturnType< MaybeAsyncResponseResolverReturnType > | AsyncGenerator< - ResponseResolverReturnType, - ResponseResolverReturnType, - ResponseResolverReturnType + MaybeAsyncResponseResolverReturnType, + MaybeAsyncResponseResolverReturnType, + MaybeAsyncResponseResolverReturnType > > From 3d6d083914df332e056faad855d66143e65f5cb9 Mon Sep 17 00:00:00 2001 From: Artem Zakharchenko Date: Fri, 19 Jul 2024 15:19:44 +0200 Subject: [PATCH 08/12] chore: print tsconfig used in type tests --- test/typings/vitest.config.mts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/typings/vitest.config.mts b/test/typings/vitest.config.mts index a97c9070e..4f879ab8e 100644 --- a/test/typings/vitest.config.mts +++ b/test/typings/vitest.config.mts @@ -32,6 +32,9 @@ export default defineConfig({ const tsConfigPath = tsConfigPaths.find((path) => fs.existsSync(path), ) as string + + console.log('Using tsconfig at: %s', tsConfigPath) + return tsConfigPath })(), }, From 63fdd4b0b07ba2946ec813b96d063f95f1d20929 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Sun, 21 Jul 2024 10:56:32 -0700 Subject: [PATCH 09/12] fix: use iterables instead of generators (#2213) --- src/core/handlers/RequestHandler.ts | 65 ++++++++++++++------------- src/core/utils/internal/isIterable.ts | 20 ++++++++- 2 files changed, 53 insertions(+), 32 deletions(-) diff --git a/src/core/handlers/RequestHandler.ts b/src/core/handlers/RequestHandler.ts index ef5653cf2..f9d34f384 100644 --- a/src/core/handlers/RequestHandler.ts +++ b/src/core/handlers/RequestHandler.ts @@ -1,5 +1,9 @@ import { getCallFrame } from '../utils/internal/getCallFrame' -import { isIterable } from '../utils/internal/isIterable' +import { + AsyncIterable, + Iterable, + isIterable, +} from '../utils/internal/isIterable' import type { ResponseResolutionContext } from '../utils/executeHandlers' import type { MaybePromise } from '../typeUtils' import { StrictRequest, StrictResponse } from '..//HttpResponse' @@ -51,12 +55,12 @@ export type AsyncResponseResolverReturnType< ResponseBodyType extends DefaultBodyType, > = MaybePromise< | ResponseResolverReturnType - | Generator< + | Iterable< MaybeAsyncResponseResolverReturnType, MaybeAsyncResponseResolverReturnType, MaybeAsyncResponseResolverReturnType > - | AsyncGenerator< + | AsyncIterable< MaybeAsyncResponseResolverReturnType, MaybeAsyncResponseResolverReturnType, MaybeAsyncResponseResolverReturnType @@ -121,18 +125,18 @@ export abstract class RequestHandler< public isUsed: boolean protected resolver: ResponseResolver - private resolverGenerator?: - | Generator< + private resolverIterator?: + | Iterator< MaybeAsyncResponseResolverReturnType, MaybeAsyncResponseResolverReturnType, MaybeAsyncResponseResolverReturnType > - | AsyncGenerator< + | AsyncIterator< MaybeAsyncResponseResolverReturnType, MaybeAsyncResponseResolverReturnType, MaybeAsyncResponseResolverReturnType > - private resolverGeneratorResult?: Response | StrictResponse + private resolverIteratorResult?: Response | StrictResponse private options?: HandlerOptions constructor(args: RequestHandlerArgs) { @@ -314,37 +318,38 @@ export abstract class RequestHandler< resolver: ResponseResolver, ): ResponseResolver { return async (info): Promise> => { - const result = this.resolverGenerator || (await resolver(info)) - - if (isIterable>(result)) { - // Opt-out from marking this handler as used. - this.isUsed = false - - if (!this.resolverGenerator) { - this.resolverGenerator = result + if (!this.resolverIterator) { + const result = await resolver(info) + if (!isIterable(result)) { + return result } + this.resolverIterator = + Symbol.iterator in result + ? result[Symbol.iterator]() + : result[Symbol.asyncIterator]() + } - const { done, value } = await this.resolverGenerator.next() - const nextResponse = await value + // Opt-out from marking this handler as used. + this.isUsed = false - if (nextResponse) { - this.resolverGeneratorResult = nextResponse.clone() - } + const { done, value } = await this.resolverIterator.next() + const nextResponse = await value - if (done) { - // A one-time generator resolver stops affecting the network - // only after it's been completely exhausted. - this.isUsed = true + if (nextResponse) { + this.resolverIteratorResult = nextResponse.clone() + } - // Clone the previously stored response so it can be read - // when receiving it repeatedly from the "done" generator. - return this.resolverGeneratorResult?.clone() - } + if (done) { + // A one-time generator resolver stops affecting the network + // only after it's been completely exhausted. + this.isUsed = true - return nextResponse + // Clone the previously stored response so it can be read + // when receiving it repeatedly from the "done" generator. + return this.resolverIteratorResult?.clone() } - return result + return nextResponse } } diff --git a/src/core/utils/internal/isIterable.ts b/src/core/utils/internal/isIterable.ts index c371158ed..670f2b649 100644 --- a/src/core/utils/internal/isIterable.ts +++ b/src/core/utils/internal/isIterable.ts @@ -1,11 +1,27 @@ +/** + * This is the same as TypeScript's `Iterable`, but with all three type parameters. + * @todo Remove once TypeScript 5.6 is the minimum. + */ +export interface Iterable { + [Symbol.iterator](): Iterator +} + +/** + * This is the same as TypeScript's `AsyncIterable`, but with all three type parameters. + * @todo Remove once TypeScript 5.6 is the minimum. + */ +export interface AsyncIterable { + [Symbol.asyncIterator](): AsyncIterator +} + /** * Determines if the given function is an iterator. */ export function isIterable( fn: any, ): fn is - | Generator - | AsyncGenerator { + | Iterable + | AsyncIterable { if (!fn) { return false } From 9f7594666ace614989ab14a8260e1a1e13eb40a6 Mon Sep 17 00:00:00 2001 From: Artem Zakharchenko Date: Tue, 23 Jul 2024 15:17:51 +0200 Subject: [PATCH 10/12] test: add type test for resolver return type --- test/typings/http.test-d.ts | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/test/typings/http.test-d.ts b/test/typings/http.test-d.ts index f782db09f..e565ebe8c 100644 --- a/test/typings/http.test-d.ts +++ b/test/typings/http.test-d.ts @@ -1,5 +1,5 @@ import { it, expectTypeOf } from 'vitest' -import { http, HttpResponse, passthrough } from 'msw' +import { http, HttpResponse, passthrough } from '../../src/core' it('supports a single path parameter', () => { http.get<{ id: string }>('/user/:id', ({ params }) => { @@ -195,3 +195,21 @@ it('infers a narrower json response type', () => { return HttpResponse.json({ a: 1, b: 2 }) }) }) + +it('errors when returning non-Response data from resolver', () => { + http.get( + '/resource', + // @ts-expect-error + () => 123, + ) + http.get( + '/resource', + // @ts-expect-error + () => 'foo', + ) + http.get( + '/resource', + // @ts-expect-error + () => ({}), + ) +}) From 5c76326beb6a89cf99c2787759af2c007a3b2d69 Mon Sep 17 00:00:00 2001 From: Artem Zakharchenko Date: Tue, 23 Jul 2024 15:21:37 +0200 Subject: [PATCH 11/12] test(generator): simplify fetch assertions --- test/node/rest-api/response/generator.test.ts | 37 ++++++++++--------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/test/node/rest-api/response/generator.test.ts b/test/node/rest-api/response/generator.test.ts index 15fb6905a..27b3ec61e 100644 --- a/test/node/rest-api/response/generator.test.ts +++ b/test/node/rest-api/response/generator.test.ts @@ -5,7 +5,10 @@ import { http, HttpResponse, delay } from 'msw' import { setupServer } from 'msw/node' const server = setupServer() -const toJson = (response: Response) => response.json() + +async function fetchJson(input: string | URL | Request, init?: RequestInit) { + return fetch(input, init).then((response) => response.json()) +} beforeAll(() => { server.listen() @@ -35,13 +38,13 @@ it('supports generator function as response resolver', async () => { ) // Must respond with yielded responses. - expect(await fetch('https://example.com/weather').then(toJson)).toEqual(11) - expect(await fetch('https://example.com/weather').then(toJson)).toEqual(12) - expect(await fetch('https://example.com/weather').then(toJson)).toEqual(13) + await expect(fetchJson('https://example.com/weather')).resolves.toEqual(11) + await expect(fetchJson('https://example.com/weather')).resolves.toEqual(12) + await expect(fetchJson('https://example.com/weather')).resolves.toEqual(13) // Must respond with the final "done" response. - expect(await fetch('https://example.com/weather').then(toJson)).toEqual(14) + await expect(fetchJson('https://example.com/weather')).resolves.toEqual(14) // Must keep responding with the final "done" response. - expect(await fetch('https://example.com/weather').then(toJson)).toEqual(14) + await expect(fetchJson('https://example.com/weather')).resolves.toEqual(14) }) it('supports async generator function as response resolver', async () => { @@ -61,11 +64,11 @@ it('supports async generator function as response resolver', async () => { }), ) - expect(await fetch('https://example.com/weather').then(toJson)).toEqual(11) - expect(await fetch('https://example.com/weather').then(toJson)).toEqual(12) - expect(await fetch('https://example.com/weather').then(toJson)).toEqual(13) - expect(await fetch('https://example.com/weather').then(toJson)).toEqual(14) - expect(await fetch('https://example.com/weather').then(toJson)).toEqual(14) + await expect(fetchJson('https://example.com/weather')).resolves.toEqual(11) + await expect(fetchJson('https://example.com/weather')).resolves.toEqual(12) + await expect(fetchJson('https://example.com/weather')).resolves.toEqual(13) + await expect(fetchJson('https://example.com/weather')).resolves.toEqual(14) + await expect(fetchJson('https://example.com/weather')).resolves.toEqual(14) }) it('supports generator function as one-time response resolver', async () => { @@ -91,16 +94,16 @@ it('supports generator function as one-time response resolver', async () => { ) // Must respond with the yielded incrementing responses. - expect(await fetch('https://example.com/weather').then(toJson)).toEqual(11) - expect(await fetch('https://example.com/weather').then(toJson)).toEqual(12) - expect(await fetch('https://example.com/weather').then(toJson)).toEqual(13) + await expect(fetchJson('https://example.com/weather')).resolves.toEqual(11) + await expect(fetchJson('https://example.com/weather')).resolves.toEqual(12) + await expect(fetchJson('https://example.com/weather')).resolves.toEqual(13) // Must respond with the "done" final response from the iterator. - expect(await fetch('https://example.com/weather').then(toJson)).toEqual(14) + await expect(fetchJson('https://example.com/weather')).resolves.toEqual(14) // Must respond with the other handler since the generator one is used. - expect(await fetch('https://example.com/weather').then(toJson)).toEqual( + await expect(fetchJson('https://example.com/weather')).resolves.toEqual( 'fallback', ) - expect(await fetch('https://example.com/weather').then(toJson)).toEqual( + await expect(fetchJson('https://example.com/weather')).resolves.toEqual( 'fallback', ) }) From 3325ae13c6d05af283fb49a3eea80ca37f400ba3 Mon Sep 17 00:00:00 2001 From: Artem Zakharchenko Date: Tue, 23 Jul 2024 15:23:51 +0200 Subject: [PATCH 12/12] test(types): import from build, not source --- test/typings/http.test-d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/typings/http.test-d.ts b/test/typings/http.test-d.ts index e565ebe8c..f40397c1a 100644 --- a/test/typings/http.test-d.ts +++ b/test/typings/http.test-d.ts @@ -1,5 +1,5 @@ import { it, expectTypeOf } from 'vitest' -import { http, HttpResponse, passthrough } from '../../src/core' +import { http, HttpResponse, passthrough } from 'msw' it('supports a single path parameter', () => { http.get<{ id: string }>('/user/:id', ({ params }) => {