-
-
Notifications
You must be signed in to change notification settings - Fork 2.7k
/
queryCache.test.js
176 lines (139 loc) 路 5.81 KB
/
queryCache.test.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
import { queryCache } from '../index'
import { act } from '@testing-library/react'
import { sleep } from './utils'
describe('queryCache', () => {
afterEach(() => {
queryCache.clear()
})
test('setQueryData does not crash if query could not be found', () => {
expect(() =>
queryCache.setQueryData(['USER', { userId: 1 }], prevUser => ({
...prevUser,
name: 'Edvin',
}))
).not.toThrow()
})
test('prefetchQuery returns the cached data on cache hits', async () => {
const fetchFn = () => Promise.resolve('data')
const first = await queryCache.prefetchQuery('key', fetchFn)
const second = await queryCache.prefetchQuery('key', fetchFn)
expect(second).toBe(first)
})
test('prefetchQuery should force fetch', async () => {
const fetchFn = () => Promise.resolve('fresh')
const first = await queryCache.prefetchQuery('key', fetchFn, {
initialData: 'initial',
force: true,
})
expect(first).toBe('fresh')
})
test('prefetchQuery should throw error when throwOnError is true', async () => {
const fetchFn = () =>
new Promise(() => {
throw new Error('error')
})
await expect(
queryCache.prefetchQuery('key', undefined, fetchFn, {
retry: false,
throwOnError: true,
})
).rejects.toThrow(new Error('error'))
})
test('should notify listeners when new query is added', () => {
const callback = jest.fn()
queryCache.subscribe(callback)
queryCache.prefetchQuery('test', () => 'data')
expect(callback).toHaveBeenCalled()
})
test('should notify subsribers when new query with initialData is added', () => {
const callback = jest.fn()
queryCache.subscribe(callback)
queryCache.prefetchQuery('test', () => {}, { initialData: 'initial' })
expect(callback).toHaveBeenCalled()
})
test('setQueryData creates a new query if query was not found, using exact', () => {
queryCache.setQueryData('foo', 'bar', { exact: true })
expect(queryCache.getQueryData('foo')).toBe('bar')
})
test('setQueryData creates a new query if query was not found', () => {
queryCache.setQueryData('baz', 'qux')
expect(queryCache.getQueryData('baz')).toBe('qux')
})
test('removeQueries does not crash when exact is provided', async () => {
const fetchFn = () => Promise.resolve('data')
// check the query was added to the cache
await queryCache.prefetchQuery('key', fetchFn)
expect(queryCache.getQuery('key')).toBeTruthy()
// check the error doesn't occur
expect(() => queryCache.removeQueries('key', { exact: true })).not.toThrow()
// check query was successful removed
expect(queryCache.getQuery('key')).toBeFalsy()
})
test('setQueryData schedules stale timeouts appropriately', async () => {
queryCache.setQueryData('key', 'test data', { staleTime: 100 })
expect(queryCache.getQuery('key').state.data).toEqual('test data')
expect(queryCache.getQuery('key').state.isStale).toEqual(false)
await sleep(50)
expect(queryCache.getQuery('key').state.isStale).toEqual(false)
await sleep(100)
expect(queryCache.getQuery('key').state.isStale).toEqual(true)
})
test('setQueryData updater function works as expected', () => {
const updater = jest.fn(oldData => `new data + ${oldData}`)
queryCache.setQueryData('updater', 'test data')
queryCache.setQueryData('updater', updater)
expect(updater).toHaveBeenCalled()
expect(queryCache.getQuery('updater').state.data).toEqual(
'new data + test data'
)
})
test('getQueries should return queries that partially match queryKey', async () => {
const fetchData1 = () => Promise.resolve('data1')
const fetchData2 = () => Promise.resolve('data2')
const fetchDifferentData = () => Promise.resolve('data3')
await queryCache.prefetchQuery(['data', { page: 1 }], fetchData1)
await queryCache.prefetchQuery(['data', { page: 2 }], fetchData2)
await queryCache.prefetchQuery(['differentData'], fetchDifferentData)
const queries = queryCache.getQueries('data')
const data = queries.map(query => query.state.data)
expect(data).toEqual(['data1', 'data2'])
})
test('stale timeout dispatch is not called if query is no longer in the query cache', async () => {
const queryKey = 'key'
const fetchData = () => Promise.resolve('data')
await queryCache.prefetchQuery(queryKey, fetchData)
const query = queryCache.getQuery(queryKey)
expect(query.state.isStale).toBe(false)
queryCache.removeQueries(queryKey)
await sleep(50)
expect(query.state.isStale).toBe(false)
})
test('query is garbage collected when unsubscribed to', async () => {
const queryKey = 'key'
const fetchData = () => Promise.resolve('data')
await queryCache.prefetchQuery(queryKey, fetchData, { cacheTime: 0 })
const query = queryCache.getQuery(queryKey)
expect(query.state.markedForGarbageCollection).toBe(false)
const unsubscribe = query.subscribe(1)
unsubscribe()
expect(query.state.markedForGarbageCollection).toBe(true)
await sleep(1)
expect(queryCache.getQuery(queryKey)).toBeUndefined()
})
test('query is not garbage collected unless markedForGarbageCollection is true', async () => {
const queryKey = 'key'
const fetchData = () => Promise.resolve(undefined)
await queryCache.prefetchQuery(queryKey, fetchData, { cacheTime: 0 })
const query = queryCache.getQuery(queryKey)
expect(query.state.markedForGarbageCollection).toBe(false)
const unsubscribe = query.subscribe(1)
unsubscribe()
expect(query.state.markedForGarbageCollection).toBe(true)
queryCache.clear()
queryCache.setQueryData(queryKey, 'data')
await sleep(1)
const newQuery = queryCache.getQuery(queryKey)
expect(newQuery.state.markedForGarbageCollection).toBe(false)
expect(newQuery.state.data).toBe('data')
})
})