@tanstack/svelte-query-persist-client 5.0.0-beta.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/LICENSE +21 -0
  2. package/dist/PersistQueryClientProvider.svelte +38 -0
  3. package/dist/PersistQueryClientProvider.svelte.d.ts +23 -0
  4. package/dist/PersistQueryClientProvider.svelte.d.ts.map +1 -0
  5. package/dist/__tests__/AwaitOnSuccess/AwaitOnSuccess.svelte +26 -0
  6. package/dist/__tests__/AwaitOnSuccess/AwaitOnSuccess.svelte.d.ts +19 -0
  7. package/dist/__tests__/AwaitOnSuccess/AwaitOnSuccess.svelte.d.ts.map +1 -0
  8. package/dist/__tests__/AwaitOnSuccess/Provider.svelte +12 -0
  9. package/dist/__tests__/AwaitOnSuccess/Provider.svelte.d.ts +24 -0
  10. package/dist/__tests__/AwaitOnSuccess/Provider.svelte.d.ts.map +1 -0
  11. package/dist/__tests__/FreshData/FreshData.svelte +31 -0
  12. package/dist/__tests__/FreshData/FreshData.svelte.d.ts +21 -0
  13. package/dist/__tests__/FreshData/FreshData.svelte.d.ts.map +1 -0
  14. package/dist/__tests__/FreshData/Provider.svelte +12 -0
  15. package/dist/__tests__/FreshData/Provider.svelte.d.ts +25 -0
  16. package/dist/__tests__/FreshData/Provider.svelte.d.ts.map +1 -0
  17. package/dist/__tests__/InitialData/InitialData.svelte +32 -0
  18. package/dist/__tests__/InitialData/InitialData.svelte.d.ts +20 -0
  19. package/dist/__tests__/InitialData/InitialData.svelte.d.ts.map +1 -0
  20. package/dist/__tests__/InitialData/Provider.svelte +11 -0
  21. package/dist/__tests__/InitialData/Provider.svelte.d.ts +24 -0
  22. package/dist/__tests__/InitialData/Provider.svelte.d.ts.map +1 -0
  23. package/dist/__tests__/OnSuccess/OnSuccess.svelte +23 -0
  24. package/dist/__tests__/OnSuccess/OnSuccess.svelte.d.ts +17 -0
  25. package/dist/__tests__/OnSuccess/OnSuccess.svelte.d.ts.map +1 -0
  26. package/dist/__tests__/OnSuccess/Provider.svelte +11 -0
  27. package/dist/__tests__/OnSuccess/Provider.svelte.d.ts +22 -0
  28. package/dist/__tests__/OnSuccess/Provider.svelte.d.ts.map +1 -0
  29. package/dist/__tests__/PersistQueryClientProvider.test.d.ts +2 -0
  30. package/dist/__tests__/PersistQueryClientProvider.test.d.ts.map +1 -0
  31. package/dist/__tests__/PersistQueryClientProvider.test.js +294 -0
  32. package/dist/__tests__/RemoveCache/Provider.svelte +10 -0
  33. package/dist/__tests__/RemoveCache/Provider.svelte.d.ts +21 -0
  34. package/dist/__tests__/RemoveCache/Provider.svelte.d.ts.map +1 -0
  35. package/dist/__tests__/RemoveCache/RemoveCache.svelte +23 -0
  36. package/dist/__tests__/RemoveCache/RemoveCache.svelte.d.ts +17 -0
  37. package/dist/__tests__/RemoveCache/RemoveCache.svelte.d.ts.map +1 -0
  38. package/dist/__tests__/RestoreCache/Provider.svelte +11 -0
  39. package/dist/__tests__/RestoreCache/Provider.svelte.d.ts +24 -0
  40. package/dist/__tests__/RestoreCache/Provider.svelte.d.ts.map +1 -0
  41. package/dist/__tests__/RestoreCache/RestoreCache.svelte +28 -0
  42. package/dist/__tests__/RestoreCache/RestoreCache.svelte.d.ts +20 -0
  43. package/dist/__tests__/RestoreCache/RestoreCache.svelte.d.ts.map +1 -0
  44. package/dist/__tests__/UseQueries/Provider.svelte +11 -0
  45. package/dist/__tests__/UseQueries/Provider.svelte.d.ts +24 -0
  46. package/dist/__tests__/UseQueries/Provider.svelte.d.ts.map +1 -0
  47. package/dist/__tests__/UseQueries/UseQueries.svelte +32 -0
  48. package/dist/__tests__/UseQueries/UseQueries.svelte.d.ts +20 -0
  49. package/dist/__tests__/UseQueries/UseQueries.svelte.d.ts.map +1 -0
  50. package/dist/__tests__/utils.d.ts +13 -0
  51. package/dist/__tests__/utils.d.ts.map +1 -0
  52. package/dist/__tests__/utils.js +22 -0
  53. package/dist/index.d.ts +3 -0
  54. package/dist/index.d.ts.map +1 -0
  55. package/dist/index.js +3 -0
  56. package/package.json +55 -0
  57. package/src/PersistQueryClientProvider.svelte +43 -0
  58. package/src/__tests__/AwaitOnSuccess/AwaitOnSuccess.svelte +31 -0
  59. package/src/__tests__/AwaitOnSuccess/Provider.svelte +17 -0
  60. package/src/__tests__/FreshData/FreshData.svelte +38 -0
  61. package/src/__tests__/FreshData/Provider.svelte +18 -0
  62. package/src/__tests__/InitialData/InitialData.svelte +39 -0
  63. package/src/__tests__/InitialData/Provider.svelte +17 -0
  64. package/src/__tests__/OnSuccess/OnSuccess.svelte +27 -0
  65. package/src/__tests__/OnSuccess/Provider.svelte +15 -0
  66. package/src/__tests__/PersistQueryClientProvider.test.ts +377 -0
  67. package/src/__tests__/RemoveCache/Provider.svelte +14 -0
  68. package/src/__tests__/RemoveCache/RemoveCache.svelte +27 -0
  69. package/src/__tests__/RestoreCache/Provider.svelte +17 -0
  70. package/src/__tests__/RestoreCache/RestoreCache.svelte +34 -0
  71. package/src/__tests__/UseQueries/Provider.svelte +17 -0
  72. package/src/__tests__/UseQueries/UseQueries.svelte +38 -0
  73. package/src/__tests__/utils.ts +34 -0
  74. package/src/index.ts +3 -0
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "@tanstack/svelte-query-persist-client",
3
+ "version": "5.0.0-beta.26",
4
+ "description": "Svelte bindings to work with persisters in TanStack/svelte-query",
5
+ "author": "Lachlan Collins",
6
+ "license": "MIT",
7
+ "repository": "tanstack/query",
8
+ "homepage": "https://tanstack.com/query",
9
+ "funding": {
10
+ "type": "github",
11
+ "url": "https://github.com/sponsors/tannerlinsley"
12
+ },
13
+ "type": "module",
14
+ "types": "dist/index.d.ts",
15
+ "module": "dist/index.js",
16
+ "svelte": "./dist/index.js",
17
+ "exports": {
18
+ ".": {
19
+ "types": "./dist/index.d.ts",
20
+ "svelte": "./dist/index.js",
21
+ "import": "./dist/index.js",
22
+ "default": "./dist/index.js"
23
+ },
24
+ "./package.json": "./package.json"
25
+ },
26
+ "files": [
27
+ "dist",
28
+ "src"
29
+ ],
30
+ "dependencies": {
31
+ "@tanstack/query-persist-client-core": "5.0.0-beta.23"
32
+ },
33
+ "devDependencies": {
34
+ "@sveltejs/package": "^2.2.0",
35
+ "@sveltejs/vite-plugin-svelte": "^2.4.2",
36
+ "@testing-library/svelte": "^4.0.3",
37
+ "eslint-plugin-svelte": "^2.32.0",
38
+ "svelte": "^4.0.0",
39
+ "svelte-check": "^3.4.4",
40
+ "@tanstack/svelte-query": "5.0.0-beta.26"
41
+ },
42
+ "peerDependencies": {
43
+ "svelte": ">=3 <5",
44
+ "@tanstack/svelte-query": "^5.0.0-beta.26"
45
+ },
46
+ "scripts": {
47
+ "clean": "rimraf ./dist && rimraf ./coverage",
48
+ "test:types": "svelte-check --tsconfig ./tsconfig.json",
49
+ "test:eslint": "eslint --ext .svelte,.ts ./src",
50
+ "test:lib": "vitest run --coverage",
51
+ "test:lib:dev": "pnpm run test:lib --watch",
52
+ "test:build": "publint --strict",
53
+ "build": "svelte-package --input ./src --output ./dist"
54
+ }
55
+ }
@@ -0,0 +1,43 @@
1
+ <script lang="ts">
2
+ import { onDestroy } from 'svelte'
3
+ import { persistQueryClient } from '@tanstack/query-persist-client-core'
4
+ import {
5
+ QueryClientProvider,
6
+ setIsRestoringContext,
7
+ } from '@tanstack/svelte-query'
8
+ import { writable } from 'svelte/store'
9
+ import type { PersistQueryClientOptions } from '@tanstack/query-persist-client-core'
10
+ import type { QueryClient } from '@tanstack/svelte-query'
11
+
12
+ export let client: QueryClient
13
+ export let onSuccess: () => Promise<unknown> | unknown = () => undefined
14
+ export let persistOptions: Omit<PersistQueryClientOptions, 'queryClient'>
15
+
16
+ const isRestoring = writable(true)
17
+ setIsRestoringContext(isRestoring)
18
+ $: {
19
+ let isStale = false
20
+ isRestoring.set(true)
21
+ const [unsubscribe, promise] = persistQueryClient({
22
+ ...persistOptions,
23
+ queryClient: client,
24
+ })
25
+ promise.then(async () => {
26
+ if (!isStale) {
27
+ try {
28
+ await onSuccess()
29
+ } finally {
30
+ isRestoring.set(false)
31
+ }
32
+ }
33
+ })
34
+ onDestroy(() => {
35
+ isStale = true
36
+ unsubscribe()
37
+ })
38
+ }
39
+ </script>
40
+
41
+ <QueryClientProvider {client}>
42
+ <slot />
43
+ </QueryClientProvider>
@@ -0,0 +1,31 @@
1
+ <script lang="ts">
2
+ import { createQuery } from '@tanstack/svelte-query'
3
+ import { get } from 'svelte/store'
4
+ import { sleep } from '../utils'
5
+ import type { Writable } from 'svelte/store'
6
+
7
+ export let key: Array<string>
8
+ export let states: Writable<Array<string>>
9
+
10
+ const state = createQuery({
11
+ queryKey: key,
12
+ queryFn: async () => {
13
+ states.update((s) => [...s, 'fetching'])
14
+ await sleep(10)
15
+ states.update((s) => [...s, 'fetched'])
16
+ return 'fetched'
17
+ },
18
+ })
19
+
20
+ let data = get(state).data
21
+ let fetchStatus = get(state).fetchStatus
22
+ state.subscribe((s) => {
23
+ data = s.data
24
+ fetchStatus = s.fetchStatus
25
+ })
26
+ </script>
27
+
28
+ <div>
29
+ <h1>{data}</h1>
30
+ <h2>fetchStatus: {fetchStatus}</h2>
31
+ </div>
@@ -0,0 +1,17 @@
1
+ <script lang="ts">
2
+ import PersistQueryClientProvider from '../../PersistQueryClientProvider.svelte'
3
+ import AwaitOnSuccess from './AwaitOnSuccess.svelte'
4
+ import type { QueryClient } from '@tanstack/svelte-query'
5
+ import type { PersistQueryClientOptions } from '@tanstack/query-persist-client-core'
6
+ import type { Writable } from 'svelte/store'
7
+
8
+ export let queryClient: QueryClient
9
+ export let persistOptions: Omit<PersistQueryClientOptions, 'queryClient'>
10
+ export let key: Array<string>
11
+ export let onSuccess: () => Promise<void>
12
+ export let states: Writable<Array<string>>
13
+ </script>
14
+
15
+ <PersistQueryClientProvider client={queryClient} {persistOptions} {onSuccess}>
16
+ <AwaitOnSuccess {key} {states} />
17
+ </PersistQueryClientProvider>
@@ -0,0 +1,38 @@
1
+ <script lang="ts">
2
+ import { createQuery } from '@tanstack/svelte-query'
3
+ import { get } from 'svelte/store'
4
+ import { sleep } from '../utils'
5
+ import type { Writable } from 'svelte/store'
6
+ import type { StatusResult } from '../utils'
7
+
8
+ export let key: Array<string>
9
+ export let states: Writable<Array<StatusResult<string>>>
10
+ export let fetched: Writable<boolean>
11
+
12
+ const state = createQuery({
13
+ queryKey: key,
14
+ queryFn: async () => {
15
+ fetched.set(true)
16
+ await sleep(10)
17
+ return 'fetched'
18
+ },
19
+
20
+ staleTime: Infinity,
21
+ })
22
+
23
+ let data = get(state).data
24
+ let fetchStatus = get(state).fetchStatus
25
+ state.subscribe((s) => {
26
+ states.update((prev) => [
27
+ ...prev,
28
+ { status: s.status, data: s.data, fetchStatus: s.fetchStatus },
29
+ ])
30
+ data = s.data
31
+ fetchStatus = s.fetchStatus
32
+ })
33
+ </script>
34
+
35
+ <div>
36
+ <h1>data: {data ?? 'null'}</h1>
37
+ <h2>fetchStatus: {fetchStatus}</h2>
38
+ </div>
@@ -0,0 +1,18 @@
1
+ <script lang="ts">
2
+ import PersistQueryClientProvider from '../../PersistQueryClientProvider.svelte'
3
+ import FreshData from './FreshData.svelte'
4
+ import type { QueryClient } from '@tanstack/svelte-query'
5
+ import type { PersistQueryClientOptions } from '@tanstack/query-persist-client-core'
6
+ import type { Writable } from 'svelte/store'
7
+ import type { StatusResult } from '../utils'
8
+
9
+ export let queryClient: QueryClient
10
+ export let persistOptions: Omit<PersistQueryClientOptions, 'queryClient'>
11
+ export let key: Array<string>
12
+ export let states: Writable<Array<StatusResult<string>>>
13
+ export let fetched: Writable<boolean>
14
+ </script>
15
+
16
+ <PersistQueryClientProvider client={queryClient} {persistOptions}>
17
+ <FreshData {key} {states} {fetched} />
18
+ </PersistQueryClientProvider>
@@ -0,0 +1,39 @@
1
+ <script lang="ts">
2
+ import { createQuery } from '@tanstack/svelte-query'
3
+ import { get } from 'svelte/store'
4
+ import { sleep } from '../utils'
5
+ import type { Writable } from 'svelte/store'
6
+ import type { StatusResult } from '../utils'
7
+
8
+ export let key: Array<string>
9
+ export let states: Writable<Array<StatusResult<string>>>
10
+
11
+ const state = createQuery({
12
+ queryKey: key,
13
+ queryFn: async () => {
14
+ await sleep(10)
15
+ return 'fetched'
16
+ },
17
+
18
+ initialData: 'initial',
19
+ // make sure that initial data is older than the hydration data
20
+ // otherwise initialData would be newer and takes precedence
21
+ initialDataUpdatedAt: 1,
22
+ })
23
+
24
+ let data = get(state).data
25
+ let fetchStatus = get(state).fetchStatus
26
+ state.subscribe((s) => {
27
+ states.update((prev) => [
28
+ ...prev,
29
+ { status: s.status, data: s.data, fetchStatus: s.fetchStatus },
30
+ ])
31
+ data = s.data
32
+ fetchStatus = s.fetchStatus
33
+ })
34
+ </script>
35
+
36
+ <div>
37
+ <h1>{data}</h1>
38
+ <h2>fetchStatus: {fetchStatus}</h2>
39
+ </div>
@@ -0,0 +1,17 @@
1
+ <script lang="ts">
2
+ import PersistQueryClientProvider from '../../PersistQueryClientProvider.svelte'
3
+ import InitialData from './InitialData.svelte'
4
+ import type { QueryClient } from '@tanstack/svelte-query'
5
+ import type { PersistQueryClientOptions } from '@tanstack/query-persist-client-core'
6
+ import type { Writable } from 'svelte/store'
7
+ import type { StatusResult } from '../utils'
8
+
9
+ export let queryClient: QueryClient
10
+ export let persistOptions: Omit<PersistQueryClientOptions, 'queryClient'>
11
+ export let key: Array<string>
12
+ export let states: Writable<Array<StatusResult<string>>>
13
+ </script>
14
+
15
+ <PersistQueryClientProvider client={queryClient} {persistOptions}>
16
+ <InitialData {key} {states} />
17
+ </PersistQueryClientProvider>
@@ -0,0 +1,27 @@
1
+ <script lang="ts">
2
+ import { createQuery } from '@tanstack/svelte-query'
3
+ import { get } from 'svelte/store'
4
+ import { sleep } from '../utils'
5
+
6
+ export let key: Array<string>
7
+
8
+ const state = createQuery({
9
+ queryKey: key,
10
+ queryFn: async () => {
11
+ await sleep(10)
12
+ return 'fetched'
13
+ },
14
+ })
15
+
16
+ let data = get(state).data
17
+ let fetchStatus = get(state).fetchStatus
18
+ state.subscribe((s) => {
19
+ data = s.data
20
+ fetchStatus = s.fetchStatus
21
+ })
22
+ </script>
23
+
24
+ <div>
25
+ <h1>{data}</h1>
26
+ <h2>fetchStatus: {fetchStatus}</h2>
27
+ </div>
@@ -0,0 +1,15 @@
1
+ <script lang="ts">
2
+ import PersistQueryClientProvider from '../../PersistQueryClientProvider.svelte'
3
+ import OnSuccess from './OnSuccess.svelte'
4
+ import type { QueryClient } from '@tanstack/svelte-query'
5
+ import type { PersistQueryClientOptions } from '@tanstack/query-persist-client-core'
6
+
7
+ export let queryClient: QueryClient
8
+ export let persistOptions: Omit<PersistQueryClientOptions, 'queryClient'>
9
+ export let key: Array<string>
10
+ export let onSuccess: () => void
11
+ </script>
12
+
13
+ <PersistQueryClientProvider client={queryClient} {persistOptions} {onSuccess}>
14
+ <OnSuccess {key} />
15
+ </PersistQueryClientProvider>
@@ -0,0 +1,377 @@
1
+ import { render, waitFor } from '@testing-library/svelte'
2
+ import { describe, expect, test, vi } from 'vitest'
3
+ import { persistQueryClientSave } from '@tanstack/query-persist-client-core'
4
+ import { get, writable } from 'svelte/store'
5
+ import AwaitOnSuccess from './AwaitOnSuccess/Provider.svelte'
6
+ import FreshData from './FreshData/Provider.svelte'
7
+ import OnSuccess from './OnSuccess/Provider.svelte'
8
+ import InitialData from './InitialData/Provider.svelte'
9
+ import RemoveCache from './RemoveCache/Provider.svelte'
10
+ import RestoreCache from './RestoreCache/Provider.svelte'
11
+ import UseQueries from './UseQueries/Provider.svelte'
12
+ import { createQueryClient, queryKey, sleep } from './utils'
13
+
14
+ import type {
15
+ PersistedClient,
16
+ Persister,
17
+ } from '@tanstack/query-persist-client-core'
18
+ import type { Writable } from 'svelte/store'
19
+ import type { StatusResult } from './utils'
20
+
21
+ const createMockPersister = (): Persister => {
22
+ let storedState: PersistedClient | undefined
23
+
24
+ return {
25
+ async persistClient(persistClient: PersistedClient) {
26
+ storedState = persistClient
27
+ },
28
+ async restoreClient() {
29
+ await sleep(10)
30
+ return storedState
31
+ },
32
+ removeClient() {
33
+ storedState = undefined
34
+ },
35
+ }
36
+ }
37
+
38
+ const createMockErrorPersister = (
39
+ removeClient: Persister['removeClient'],
40
+ ): [Error, Persister] => {
41
+ const error = new Error('restore failed')
42
+ return [
43
+ error,
44
+ {
45
+ async persistClient() {
46
+ // noop
47
+ },
48
+ async restoreClient() {
49
+ await sleep(10)
50
+ throw error
51
+ },
52
+ removeClient,
53
+ },
54
+ ]
55
+ }
56
+
57
+ describe('PersistQueryClientProvider', () => {
58
+ test('restores cache from persister', async () => {
59
+ const key = queryKey()
60
+ const states: Writable<Array<StatusResult<string>>> = writable([])
61
+
62
+ const queryClient = createQueryClient()
63
+ await queryClient.prefetchQuery({
64
+ queryKey: key,
65
+ queryFn: () => Promise.resolve('hydrated'),
66
+ })
67
+
68
+ const persister = createMockPersister()
69
+
70
+ await persistQueryClientSave({ queryClient, persister })
71
+
72
+ queryClient.clear()
73
+
74
+ const rendered = render(RestoreCache, {
75
+ props: {
76
+ queryClient,
77
+ persistOptions: { persister },
78
+ key,
79
+ states,
80
+ },
81
+ })
82
+
83
+ await waitFor(() => rendered.getByText('fetchStatus: idle'))
84
+ await waitFor(() => rendered.getByText('hydrated'))
85
+ await waitFor(() => rendered.getByText('fetched'))
86
+
87
+ const states_ = get(states)
88
+ expect(states_).toHaveLength(4)
89
+
90
+ expect(states_[0]).toMatchObject({
91
+ status: 'pending',
92
+ fetchStatus: 'idle',
93
+ data: undefined,
94
+ })
95
+
96
+ expect(states_[1]).toMatchObject({
97
+ status: 'success',
98
+ fetchStatus: 'fetching',
99
+ data: 'hydrated',
100
+ })
101
+
102
+ expect(states_[2]).toMatchObject({
103
+ status: 'success',
104
+ fetchStatus: 'fetching',
105
+ data: 'hydrated',
106
+ })
107
+
108
+ expect(states_[3]).toMatchObject({
109
+ status: 'success',
110
+ fetchStatus: 'idle',
111
+ data: 'fetched',
112
+ })
113
+ })
114
+
115
+ test('should also put useQueries into idle state', async () => {
116
+ const key = queryKey()
117
+ const states: Writable<Array<StatusResult<string>>> = writable([])
118
+
119
+ const queryClient = createQueryClient()
120
+ await queryClient.prefetchQuery({
121
+ queryKey: key,
122
+ queryFn: () => Promise.resolve('hydrated'),
123
+ })
124
+
125
+ const persister = createMockPersister()
126
+
127
+ await persistQueryClientSave({ queryClient, persister })
128
+
129
+ queryClient.clear()
130
+
131
+ const rendered = render(UseQueries, {
132
+ props: {
133
+ queryClient,
134
+ persistOptions: { persister },
135
+ key,
136
+ states,
137
+ },
138
+ })
139
+
140
+ await waitFor(() => rendered.getByText('fetchStatus: idle'))
141
+ await waitFor(() => rendered.getByText('hydrated'))
142
+ await waitFor(() => rendered.getByText('fetched'))
143
+
144
+ const states_ = get(states)
145
+
146
+ expect(states_).toHaveLength(4)
147
+
148
+ expect(states_[0]).toMatchObject({
149
+ status: 'pending',
150
+ fetchStatus: 'idle',
151
+ data: undefined,
152
+ })
153
+
154
+ expect(states_[1]).toMatchObject({
155
+ status: 'success',
156
+ fetchStatus: 'fetching',
157
+ data: 'hydrated',
158
+ })
159
+
160
+ expect(states_[2]).toMatchObject({
161
+ status: 'success',
162
+ fetchStatus: 'fetching',
163
+ data: 'hydrated',
164
+ })
165
+
166
+ expect(states_[3]).toMatchObject({
167
+ status: 'success',
168
+ fetchStatus: 'idle',
169
+ data: 'fetched',
170
+ })
171
+ })
172
+
173
+ test('should show initialData while restoring', async () => {
174
+ const key = queryKey()
175
+ const states: Writable<Array<StatusResult<string>>> = writable([])
176
+
177
+ const queryClient = createQueryClient()
178
+ await queryClient.prefetchQuery({
179
+ queryKey: key,
180
+ queryFn: () => Promise.resolve('hydrated'),
181
+ })
182
+
183
+ const persister = createMockPersister()
184
+
185
+ await persistQueryClientSave({ queryClient, persister })
186
+
187
+ queryClient.clear()
188
+
189
+ const rendered = render(InitialData, {
190
+ props: {
191
+ queryClient,
192
+ persistOptions: { persister },
193
+ key,
194
+ states,
195
+ },
196
+ })
197
+
198
+ await waitFor(() => rendered.getByText('initial'))
199
+ await waitFor(() => rendered.getByText('hydrated'))
200
+ await waitFor(() => rendered.getByText('fetched'))
201
+
202
+ const states_ = get(states)
203
+ expect(states_).toHaveLength(4)
204
+
205
+ expect(states_[0]).toMatchObject({
206
+ status: 'success',
207
+ fetchStatus: 'idle',
208
+ data: 'initial',
209
+ })
210
+
211
+ expect(states_[1]).toMatchObject({
212
+ status: 'success',
213
+ fetchStatus: 'fetching',
214
+ data: 'hydrated',
215
+ })
216
+
217
+ expect(states_[2]).toMatchObject({
218
+ status: 'success',
219
+ fetchStatus: 'fetching',
220
+ data: 'hydrated',
221
+ })
222
+
223
+ expect(states_[3]).toMatchObject({
224
+ status: 'success',
225
+ fetchStatus: 'idle',
226
+ data: 'fetched',
227
+ })
228
+ })
229
+
230
+ test('should not refetch after restoring when data is fresh', async () => {
231
+ const key = queryKey()
232
+ const states: Writable<Array<StatusResult<string>>> = writable([])
233
+
234
+ const queryClient = createQueryClient()
235
+ await queryClient.prefetchQuery({
236
+ queryKey: key,
237
+ queryFn: () => Promise.resolve('hydrated'),
238
+ })
239
+
240
+ const persister = createMockPersister()
241
+
242
+ await persistQueryClientSave({ queryClient, persister })
243
+
244
+ queryClient.clear()
245
+
246
+ const fetched = writable(false)
247
+
248
+ const rendered = render(FreshData, {
249
+ props: {
250
+ queryClient,
251
+ persistOptions: { persister },
252
+ key,
253
+ states,
254
+ fetched,
255
+ },
256
+ })
257
+
258
+ await waitFor(() => rendered.getByText('data: null'))
259
+ await waitFor(() => rendered.getByText('data: hydrated'))
260
+
261
+ const states_ = get(states)
262
+ expect(states_).toHaveLength(2)
263
+
264
+ expect(get(fetched)).toBe(false)
265
+
266
+ expect(states_[0]).toMatchObject({
267
+ status: 'pending',
268
+ fetchStatus: 'idle',
269
+ data: undefined,
270
+ })
271
+
272
+ expect(states_[1]).toMatchObject({
273
+ status: 'success',
274
+ fetchStatus: 'idle',
275
+ data: 'hydrated',
276
+ })
277
+ })
278
+
279
+ test('should call onSuccess after successful restoring', async () => {
280
+ const key = queryKey()
281
+
282
+ const queryClient = createQueryClient()
283
+ await queryClient.prefetchQuery({
284
+ queryKey: key,
285
+ queryFn: () => Promise.resolve('hydrated'),
286
+ })
287
+
288
+ const persister = createMockPersister()
289
+
290
+ await persistQueryClientSave({ queryClient, persister })
291
+
292
+ queryClient.clear()
293
+
294
+ const onSuccess = vi.fn()
295
+
296
+ const rendered = render(OnSuccess, {
297
+ props: {
298
+ queryClient,
299
+ persistOptions: { persister },
300
+ key,
301
+ onSuccess,
302
+ },
303
+ })
304
+
305
+ expect(onSuccess).toHaveBeenCalledTimes(0)
306
+
307
+ await waitFor(() => rendered.getByText('hydrated'))
308
+ expect(onSuccess).toHaveBeenCalledTimes(1)
309
+ await waitFor(() => rendered.getByText('fetched'))
310
+ })
311
+
312
+ test('should await onSuccess after successful restoring', async () => {
313
+ const key = queryKey()
314
+
315
+ const queryClient = createQueryClient()
316
+ await queryClient.prefetchQuery({
317
+ queryKey: key,
318
+ queryFn: () => Promise.resolve('hydrated'),
319
+ })
320
+
321
+ const persister = createMockPersister()
322
+
323
+ await persistQueryClientSave({ queryClient, persister })
324
+
325
+ queryClient.clear()
326
+
327
+ const states: Writable<Array<string>> = writable([])
328
+
329
+ const rendered = render(AwaitOnSuccess, {
330
+ props: {
331
+ queryClient,
332
+ persistOptions: { persister },
333
+ key,
334
+ states,
335
+ onSuccess: async () => {
336
+ states.update((s) => [...s, 'onSuccess'])
337
+ await sleep(20)
338
+ states.update((s) => [...s, 'onSuccess done'])
339
+ },
340
+ },
341
+ })
342
+
343
+ await waitFor(() => rendered.getByText('hydrated'))
344
+ await waitFor(() => rendered.getByText('fetched'))
345
+ expect(get(states)).toEqual([
346
+ 'onSuccess',
347
+ 'onSuccess done',
348
+ 'fetching',
349
+ 'fetched',
350
+ ])
351
+ })
352
+
353
+ test('should remove cache after non-successful restoring', async () => {
354
+ const key = queryKey()
355
+ const consoleMock = vi.spyOn(console, 'error')
356
+ const consoleWarn = vi
357
+ .spyOn(console, 'warn')
358
+ .mockImplementation(() => undefined)
359
+ consoleMock.mockImplementation(() => undefined)
360
+
361
+ const queryClient = createQueryClient()
362
+ const removeClient = vi.fn()
363
+
364
+ const [error, persister] = createMockErrorPersister(removeClient)
365
+
366
+ const rendered = render(RemoveCache, {
367
+ props: { queryClient, persistOptions: { persister }, key },
368
+ })
369
+
370
+ await waitFor(() => rendered.getByText('fetched'))
371
+ expect(removeClient).toHaveBeenCalledTimes(1)
372
+ expect(consoleMock).toHaveBeenCalledTimes(1)
373
+ expect(consoleMock).toHaveBeenNthCalledWith(1, error)
374
+ consoleMock.mockRestore()
375
+ consoleWarn.mockRestore()
376
+ })
377
+ })