@@ -11,6 +11,7 @@ import {
11
11
OperationVariables ,
12
12
TypedDocumentNode ,
13
13
WatchQueryFetchPolicy ,
14
+ WatchQueryOptions ,
14
15
} from "../../../core" ;
15
16
import { InMemoryCache } from "../../../cache" ;
16
17
import { ApolloProvider } from "../../context" ;
@@ -36,6 +37,7 @@ import {
36
37
} from "../../../testing/internal" ;
37
38
import { useApolloClient } from "../useApolloClient" ;
38
39
import { useLazyQuery } from "../useLazyQuery" ;
40
+ import { mockFetchQuery } from "../../../core/__tests__/ObservableQuery" ;
39
41
40
42
const IS_REACT_17 = React . version . startsWith ( "17" ) ;
41
43
@@ -7071,6 +7073,131 @@ describe("useQuery Hook", () => {
7071
7073
7072
7074
expect ( reasons ) . toEqual ( [ "variables-changed" , "after-fetch" ] ) ;
7073
7075
} ) ;
7076
+
7077
+ it ( "should prioritize a `nextFetchPolicy` function over a `fetchPolicy` option when changing variables" , async ( ) => {
7078
+ const query = gql `
7079
+ {
7080
+ hello
7081
+ }
7082
+ ` ;
7083
+ const link = new MockLink ( [
7084
+ {
7085
+ request : { query, variables : { id : 1 } } ,
7086
+ result : { data : { hello : "from link" } } ,
7087
+ delay : 10 ,
7088
+ } ,
7089
+ {
7090
+ request : { query, variables : { id : 2 } } ,
7091
+ result : { data : { hello : "from link2" } } ,
7092
+ delay : 10 ,
7093
+ } ,
7094
+ ] ) ;
7095
+
7096
+ const client = new ApolloClient ( {
7097
+ cache : new InMemoryCache ( ) ,
7098
+ link,
7099
+ } ) ;
7100
+
7101
+ const mocks = mockFetchQuery ( client [ "queryManager" ] ) ;
7102
+
7103
+ const expectQueryTriggered = (
7104
+ nth : number ,
7105
+ fetchPolicy : WatchQueryFetchPolicy
7106
+ ) => {
7107
+ expect ( mocks . fetchQueryByPolicy ) . toHaveBeenCalledTimes ( nth ) ;
7108
+ expect ( mocks . fetchQueryByPolicy ) . toHaveBeenNthCalledWith (
7109
+ nth ,
7110
+ expect . anything ( ) ,
7111
+ expect . objectContaining ( { fetchPolicy } ) ,
7112
+ expect . any ( Number )
7113
+ ) ;
7114
+ } ;
7115
+ let nextFetchPolicy : WatchQueryOptions <
7116
+ OperationVariables ,
7117
+ any
7118
+ > [ "nextFetchPolicy" ] = ( _ , context ) => {
7119
+ if ( context . reason === "variables-changed" ) {
7120
+ return "cache-and-network" ;
7121
+ } else if ( context . reason === "after-fetch" ) {
7122
+ return "cache-only" ;
7123
+ }
7124
+ throw new Error ( "should never happen" ) ;
7125
+ } ;
7126
+ nextFetchPolicy = jest . fn ( nextFetchPolicy ) ;
7127
+
7128
+ const { result, rerender } = renderHook <
7129
+ QueryResult ,
7130
+ {
7131
+ variables : { id : number } ;
7132
+ }
7133
+ > (
7134
+ ( { variables } ) =>
7135
+ useQuery ( query , {
7136
+ fetchPolicy : "network-only" ,
7137
+ variables,
7138
+ notifyOnNetworkStatusChange : true ,
7139
+ nextFetchPolicy,
7140
+ } ) ,
7141
+ {
7142
+ initialProps : {
7143
+ variables : { id : 1 } ,
7144
+ } ,
7145
+ wrapper : ( { children } ) => (
7146
+ < ApolloProvider client = { client } > { children } </ ApolloProvider >
7147
+ ) ,
7148
+ }
7149
+ ) ;
7150
+ // first network request triggers with initial fetchPolicy
7151
+ expectQueryTriggered ( 1 , "network-only" ) ;
7152
+
7153
+ await waitFor ( ( ) => {
7154
+ expect ( result . current . networkStatus ) . toBe ( NetworkStatus . ready ) ;
7155
+ } ) ;
7156
+
7157
+ expect ( nextFetchPolicy ) . toHaveBeenCalledTimes ( 1 ) ;
7158
+ expect ( nextFetchPolicy ) . toHaveBeenNthCalledWith (
7159
+ 1 ,
7160
+ "network-only" ,
7161
+ expect . objectContaining ( {
7162
+ reason : "after-fetch" ,
7163
+ } )
7164
+ ) ;
7165
+ // `nextFetchPolicy(..., {reason: "after-fetch"})` changed it to
7166
+ // cache-only
7167
+ expect ( result . current . observable . options . fetchPolicy ) . toBe ( "cache-only" ) ;
7168
+
7169
+ rerender ( {
7170
+ variables : { id : 2 } ,
7171
+ } ) ;
7172
+
7173
+ expect ( nextFetchPolicy ) . toHaveBeenNthCalledWith (
7174
+ 2 ,
7175
+ // has been reset to the initial `fetchPolicy` of "network-only" because
7176
+ // we changed variables, then `nextFetchPolicy` is called
7177
+ "network-only" ,
7178
+ expect . objectContaining ( {
7179
+ reason : "variables-changed" ,
7180
+ } )
7181
+ ) ;
7182
+ // the return value of `nextFetchPolicy(..., {reason: "variables-changed"})`
7183
+ expectQueryTriggered ( 2 , "cache-and-network" ) ;
7184
+
7185
+ await waitFor ( ( ) => {
7186
+ expect ( result . current . networkStatus ) . toBe ( NetworkStatus . ready ) ;
7187
+ } ) ;
7188
+
7189
+ expect ( nextFetchPolicy ) . toHaveBeenCalledTimes ( 3 ) ;
7190
+ expect ( nextFetchPolicy ) . toHaveBeenNthCalledWith (
7191
+ 3 ,
7192
+ "cache-and-network" ,
7193
+ expect . objectContaining ( {
7194
+ reason : "after-fetch" ,
7195
+ } )
7196
+ ) ;
7197
+ // `nextFetchPolicy(..., {reason: "after-fetch"})` changed it to
7198
+ // cache-only
7199
+ expect ( result . current . observable . options . fetchPolicy ) . toBe ( "cache-only" ) ;
7200
+ } ) ;
7074
7201
} ) ;
7075
7202
7076
7203
describe ( "Missing Fields" , ( ) => {
0 commit comments