@@ -2,14 +2,16 @@ import { HttpResponse, type StrictResponse } from "msw";
2
2
import { afterAll , beforeAll , describe , expect , expectTypeOf , it } from "vitest" ;
3
3
import createClient , {
4
4
type MethodResponse ,
5
+ type FetchOptions ,
6
+ type HeadersOptions ,
5
7
type Middleware ,
6
8
type MiddlewareCallbackParams ,
7
9
type QuerySerializerOptions ,
8
10
type Client ,
9
11
type PathBasedClient ,
10
12
createPathBasedClient ,
11
13
} from "../src/index.js" ;
12
- import { server , baseUrl , useMockRequestHandler , toAbsoluteURL } from "./fixtures/mock-server.js" ;
14
+ import { baseUrl , server , toAbsoluteURL , useMockRequestHandler } from "./fixtures/mock-server.js" ;
13
15
import type { paths } from "./fixtures/api.js" ;
14
16
15
17
beforeAll ( ( ) => {
@@ -817,12 +819,7 @@ describe("client", () => {
817
819
await client . GET ( "/self" ) ;
818
820
819
821
// assert default headers were passed
820
- expect ( getRequest ( ) . headers ) . toEqual (
821
- new Headers ( {
822
- ...headers , // assert new header got passed
823
- "Content-Type" : "application/json" , // probably doesn’t need to get tested, but this was simpler than writing lots of code to ignore these
824
- } ) ,
825
- ) ;
822
+ expect ( getRequest ( ) . headers ) . toEqual ( new Headers ( headers ) ) ;
826
823
} ) ;
827
824
828
825
it ( "can be overridden" , async ( ) => {
@@ -848,7 +845,6 @@ describe("client", () => {
848
845
expect ( getRequest ( ) . headers ) . toEqual (
849
846
new Headers ( {
850
847
"Cache-Control" : "no-cache" ,
851
- "Content-Type" : "application/json" ,
852
848
} ) ,
853
849
) ;
854
850
} ) ;
@@ -892,6 +888,139 @@ describe("client", () => {
892
888
} ) ;
893
889
} ) ;
894
890
891
+ describe ( "content-type" , ( ) => {
892
+ const BODY_ACCEPTING_METHODS = [ [ "PUT" ] , [ "POST" ] , [ "DELETE" ] , [ "OPTIONS" ] , [ "PATCH" ] ] as const ;
893
+ const ALL_METHODS = [ ...BODY_ACCEPTING_METHODS , [ "GET" ] , [ "HEAD" ] ] as const ;
894
+
895
+ const fireRequestAndGetContentType = async ( options : {
896
+ defaultHeaders ?: HeadersOptions ;
897
+ method : ( typeof ALL_METHODS ) [ number ] [ number ] ;
898
+ fetchOptions : FetchOptions < any > ;
899
+ } ) => {
900
+ const client = createClient < any > ( { baseUrl, headers : options . defaultHeaders } ) ;
901
+ const { getRequest } = useMockRequestHandler ( {
902
+ baseUrl,
903
+ method : "all" ,
904
+ path : "/blogposts-optional" ,
905
+ status : 200 ,
906
+ } ) ;
907
+ await client [ options . method ] ( "/blogposts-optional" , options . fetchOptions as any ) ;
908
+
909
+ const request = getRequest ( ) ;
910
+ return request . headers . get ( "content-type" ) ;
911
+ } ;
912
+
913
+ it . each ( ALL_METHODS ) ( "no content-type for body-less requests - %s" , async ( method ) => {
914
+ const contentType = await fireRequestAndGetContentType ( {
915
+ method,
916
+ fetchOptions : { } ,
917
+ } ) ;
918
+
919
+ expect ( contentType ) . toBe ( null ) ;
920
+ } ) ;
921
+
922
+ it . each ( ALL_METHODS ) ( "no content-type for `undefined` body requests - %s" , async ( method ) => {
923
+ const contentType = await fireRequestAndGetContentType ( {
924
+ method,
925
+ fetchOptions : {
926
+ body : undefined ,
927
+ } ,
928
+ } ) ;
929
+
930
+ expect ( contentType ) . toBe ( null ) ;
931
+ } ) ;
932
+
933
+ const BODIES = [ { prop : "a" } , { } , "" , "str" , null , false , 0 , 1 , new Date ( "2024-08-07T09:52:00.836Z" ) ] as const ;
934
+ // const BODIES = ["str"] as const;
935
+ const METHOD_BODY_COMBINATIONS = BODY_ACCEPTING_METHODS . flatMap ( ( [ method ] ) =>
936
+ BODIES . map ( ( body ) => [ method , body ] as const ) ,
937
+ ) ;
938
+
939
+ it . each ( METHOD_BODY_COMBINATIONS ) (
940
+ "implicit default content-type for body-full requests - %s, %j" ,
941
+ async ( method , body ) => {
942
+ const contentType = await fireRequestAndGetContentType ( {
943
+ method,
944
+ fetchOptions : {
945
+ body,
946
+ } ,
947
+ } ) ;
948
+
949
+ expect ( contentType ) . toBe ( "application/json" ) ;
950
+ } ,
951
+ ) ;
952
+
953
+ it . each ( METHOD_BODY_COMBINATIONS ) (
954
+ "provided default content-type for body-full requests - %s, %j" ,
955
+ async ( method , body ) => {
956
+ const contentType = await fireRequestAndGetContentType ( {
957
+ defaultHeaders : {
958
+ "content-type" : "application/my-json" ,
959
+ } ,
960
+ method,
961
+ fetchOptions : {
962
+ body,
963
+ } ,
964
+ } ) ;
965
+
966
+ expect ( contentType ) . toBe ( "application/my-json" ) ;
967
+ } ,
968
+ ) ;
969
+
970
+ it . each ( METHOD_BODY_COMBINATIONS ) (
971
+ "native-fetch default content-type for body-full requests, when default is suppressed - %s, %j" ,
972
+ async ( method , body ) => {
973
+ const contentType = await fireRequestAndGetContentType ( {
974
+ defaultHeaders : {
975
+ "content-type" : null ,
976
+ } ,
977
+ method,
978
+ fetchOptions : {
979
+ body,
980
+ } ,
981
+ } ) ;
982
+ // the fetch implementation won't allow sending a body without content-type,
983
+ // so it invents one up and sends it, hopefully this will be consistent across
984
+ // local environments and won't make the tests flaky
985
+ expect ( contentType ) . toBe ( "text/plain;charset=UTF-8" ) ;
986
+ } ,
987
+ ) ;
988
+
989
+ it . each ( METHOD_BODY_COMBINATIONS ) (
990
+ "specified content-type for body-full requests - %s, %j" ,
991
+ async ( method , body ) => {
992
+ const contentType = await fireRequestAndGetContentType ( {
993
+ method,
994
+ fetchOptions : {
995
+ body,
996
+ headers : {
997
+ "content-type" : "application/my-json" ,
998
+ } ,
999
+ } ,
1000
+ } ) ;
1001
+
1002
+ expect ( contentType ) . toBe ( "application/my-json" ) ;
1003
+ } ,
1004
+ ) ;
1005
+
1006
+ it . each ( METHOD_BODY_COMBINATIONS ) (
1007
+ "specified content-type for body-full requests, even when default is suppressed - %s, %j" ,
1008
+ async ( method , body ) => {
1009
+ const contentType = await fireRequestAndGetContentType ( {
1010
+ method,
1011
+ fetchOptions : {
1012
+ body,
1013
+ headers : {
1014
+ "content-type" : "application/my-json" ,
1015
+ } ,
1016
+ } ,
1017
+ } ) ;
1018
+
1019
+ expect ( contentType ) . toBe ( "application/my-json" ) ;
1020
+ } ,
1021
+ ) ;
1022
+ } ) ;
1023
+
895
1024
describe ( "fetch" , ( ) => {
896
1025
it ( "createClient" , async ( ) => {
897
1026
function createCustomFetch ( data : any ) {
0 commit comments