1+ import { Headers as HeadersPolyfill } from 'headers-polyfill'
12import { getCallFrame } from '../utils/internal/getCallFrame'
23import {
34 isIterable ,
@@ -12,6 +13,7 @@ import {
1213 type DefaultUnsafeFetchResponse ,
1314} from '../HttpResponse'
1415import type { GraphQLRequestBody } from './GraphQLHandler'
16+ import { getRawSetCookie } from '../utils/HttpResponse/decorators'
1517
1618export type DefaultRequestMultipartBody = Record <
1719 string ,
@@ -335,7 +337,7 @@ export abstract class RequestHandler<
335337 ...resolverExtras ,
336338 requestId : args . requestId ,
337339 request : args . request ,
338- } ) as Promise < Response >
340+ } ) as Promise < Response | undefined >
339341 ) . catch ( ( errorOrResponse ) => {
340342 // Allow throwing a Response instance in a response resolver.
341343 if ( errorOrResponse instanceof Response ) {
@@ -348,6 +350,10 @@ export abstract class RequestHandler<
348350
349351 const mockedResponse = await mockedResponsePromise
350352
353+ if ( mockedResponse ) {
354+ forwardResponseCookies ( mockedResponse )
355+ }
356+
351357 const executionResult = this . createExecutionResult ( {
352358 // Pass the cloned request to the result so that logging
353359 // and other consumers could read its body once more.
@@ -416,3 +422,32 @@ export abstract class RequestHandler<
416422 }
417423 }
418424}
425+
426+ /**
427+ * Forwards the cookies from the given response to `document.cookie`.
428+ */
429+ export function forwardResponseCookies ( response : Response ) : void {
430+ // Cookie forwarding is only relevant in the browser.
431+ if ( typeof document === 'undefined' ) {
432+ return
433+ }
434+
435+ const responseCookies = getRawSetCookie ( response )
436+
437+ if ( ! responseCookies ) {
438+ return
439+ }
440+
441+ // Write the mocked response cookies to the document.
442+ // Use `headers-polyfill` to get the Set-Cookie header value correctly.
443+ // This is an alternative until TypeScript 5.2
444+ // and Node.js v20 become the minimum supported versions
445+ // and "Headers.prototype.getSetCookie" can be used directly.
446+ const allResponseCookies = HeadersPolyfill . prototype . getSetCookie . call (
447+ new Headers ( [ [ 'set-cookie' , responseCookies ] ] ) ,
448+ )
449+
450+ for ( const cookieString of allResponseCookies ) {
451+ document . cookie = cookieString
452+ }
453+ }
0 commit comments