@@ -29,6 +29,10 @@ const authSlice = createSlice({
29
29
30
30
const storeRef = setupApiStore ( api , { auth : authSlice . reducer } )
31
31
32
+ function delay ( ms : number ) {
33
+ return new Promise ( ( resolve ) => setTimeout ( resolve , ms ) )
34
+ }
35
+
32
36
it ( 'only resets the api state when resetApiState is dispatched' , async ( ) => {
33
37
storeRef . store . dispatch ( { type : 'unrelated' } ) // trigger "registered middleware" into place
34
38
const initialState = storeRef . store . getState ( )
@@ -77,3 +81,100 @@ it('only resets the api state when resetApiState is dispatched', async () => {
77
81
78
82
expect ( storeRef . store . getState ( ) ) . toEqual ( initialState )
79
83
} )
84
+
85
+ describe . only ( '`merge` callback' , ( ) => {
86
+ const baseQuery = ( args ?: any ) => ( { data : args } )
87
+
88
+ interface Todo {
89
+ id : string
90
+ text : string
91
+ }
92
+
93
+ it ( 'Calls `merge` once there is existing data, and allows mutations of cache state' , async ( ) => {
94
+ let mergeCalled = false
95
+ let queryFnCalls = 0
96
+ const todoTexts = [ 'A' , 'B' , 'C' , 'D' ]
97
+
98
+ const api = createApi ( {
99
+ baseQuery,
100
+ endpoints : ( build ) => ( {
101
+ getTodos : build . query < Todo [ ] , void > ( {
102
+ async queryFn ( ) {
103
+ const text = todoTexts [ queryFnCalls ]
104
+ return { data : [ { id : `${ queryFnCalls ++ } ` , text } ] }
105
+ } ,
106
+ merge ( currentCacheValue , responseData ) {
107
+ mergeCalled = true
108
+ currentCacheValue . push ( ...responseData )
109
+ } ,
110
+ } ) ,
111
+ } ) ,
112
+ } )
113
+
114
+ const storeRef = setupApiStore ( api , undefined , {
115
+ withoutTestLifecycles : true ,
116
+ } )
117
+
118
+ const selectTodoEntry = api . endpoints . getTodos . select ( )
119
+
120
+ const res = storeRef . store . dispatch ( api . endpoints . getTodos . initiate ( ) )
121
+ await res
122
+ expect ( mergeCalled ) . toBe ( false )
123
+ const todoEntry1 = selectTodoEntry ( storeRef . store . getState ( ) )
124
+ expect ( todoEntry1 . data ) . toEqual ( [ { id : '0' , text : 'A' } ] )
125
+
126
+ res . refetch ( )
127
+
128
+ await delay ( 10 )
129
+
130
+ expect ( mergeCalled ) . toBe ( true )
131
+ const todoEntry2 = selectTodoEntry ( storeRef . store . getState ( ) )
132
+
133
+ expect ( todoEntry2 . data ) . toEqual ( [
134
+ { id : '0' , text : 'A' } ,
135
+ { id : '1' , text : 'B' } ,
136
+ ] )
137
+ } )
138
+
139
+ it ( 'Allows returning a different value from `merge`' , async ( ) => {
140
+ let firstQueryFnCall = true
141
+
142
+ const api = createApi ( {
143
+ baseQuery,
144
+ endpoints : ( build ) => ( {
145
+ getTodos : build . query < Todo [ ] , void > ( {
146
+ async queryFn ( ) {
147
+ const item = firstQueryFnCall
148
+ ? { id : '0' , text : 'A' }
149
+ : { id : '1' , text : 'B' }
150
+ firstQueryFnCall = false
151
+ return { data : [ item ] }
152
+ } ,
153
+ merge ( currentCacheValue , responseData ) {
154
+ return responseData
155
+ } ,
156
+ } ) ,
157
+ } ) ,
158
+ } )
159
+
160
+ const storeRef = setupApiStore ( api , undefined , {
161
+ withoutTestLifecycles : true ,
162
+ } )
163
+
164
+ const selectTodoEntry = api . endpoints . getTodos . select ( )
165
+
166
+ const res = storeRef . store . dispatch ( api . endpoints . getTodos . initiate ( ) )
167
+ await res
168
+
169
+ const todoEntry1 = selectTodoEntry ( storeRef . store . getState ( ) )
170
+ expect ( todoEntry1 . data ) . toEqual ( [ { id : '0' , text : 'A' } ] )
171
+
172
+ res . refetch ( )
173
+
174
+ await delay ( 10 )
175
+
176
+ const todoEntry2 = selectTodoEntry ( storeRef . store . getState ( ) )
177
+
178
+ expect ( todoEntry2 . data ) . toEqual ( [ { id : '1' , text : 'B' } ] )
179
+ } )
180
+ } )
0 commit comments