Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { describe, expect, test, vi } from 'vitest'
import { render, screen, waitFor } from '@solidjs/testing-library'
import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'
import { render, screen } from '@solidjs/testing-library'
import { QueryClient, useQueries, useQuery } from '@tanstack/solid-query'
import { persistQueryClientSave } from '@tanstack/query-persist-client-core'
import { createEffect, createSignal, onMount } from 'solid-js'
Expand All @@ -18,8 +18,7 @@ const createMockPersister = (): Persister => {
storedState = persistClient
},
async restoreClient() {
await sleep(10)
return storedState
return sleep(10).then(() => storedState)
},
removeClient() {
storedState = undefined
Expand Down Expand Up @@ -47,6 +46,14 @@ const createMockErrorPersister = (
}

describe('PersistQueryClientProvider', () => {
beforeEach(() => {
vi.useFakeTimers()
})

afterEach(() => {
vi.useRealTimers()
})

test('restores cache from persister', async () => {
const key = queryKey()
const states: Array<{
Expand All @@ -56,24 +63,23 @@ describe('PersistQueryClientProvider', () => {
}> = []

const queryClient = new QueryClient()
await queryClient.prefetchQuery({
queryClient.prefetchQuery({
queryKey: key,
queryFn: () => Promise.resolve('hydrated'),
queryFn: () => sleep(10).then(() => 'hydrated'),
})
await vi.advanceTimersByTimeAsync(10)

const persister = createMockPersister()

await persistQueryClientSave({ queryClient, persister })
persistQueryClientSave({ queryClient, persister })
await vi.advanceTimersByTimeAsync(0)

queryClient.clear()

function Page() {
const state = useQuery(() => ({
queryKey: key,
queryFn: async () => {
await sleep(10)
return 'fetched'
},
queryFn: () => sleep(10).then(() => 'fetched'),
}))
createEffect(() =>
states.push({
Expand All @@ -100,9 +106,11 @@ describe('PersistQueryClientProvider', () => {
</PersistQueryClientProvider>
))

await waitFor(() => screen.getByText('fetchStatus: idle'))
await waitFor(() => screen.getByText('hydrated'))
await waitFor(() => screen.getByText('fetched'))
expect(screen.getByText('fetchStatus: idle')).toBeInTheDocument()
await vi.advanceTimersByTimeAsync(10)
expect(screen.getByText('hydrated')).toBeInTheDocument()
await vi.advanceTimersByTimeAsync(10)
expect(screen.getByText('fetched')).toBeInTheDocument()

expect(states).toHaveLength(3)

Expand Down Expand Up @@ -134,14 +142,16 @@ describe('PersistQueryClientProvider', () => {
}> = []

const queryClient = new QueryClient()
await queryClient.prefetchQuery({
queryClient.prefetchQuery({
queryKey: key,
queryFn: () => Promise.resolve('hydrated'),
queryFn: () => sleep(10).then(() => 'hydrated'),
})
await vi.advanceTimersByTimeAsync(10)

const persister = createMockPersister()

await persistQueryClientSave({ queryClient, persister })
persistQueryClientSave({ queryClient, persister })
await vi.advanceTimersByTimeAsync(0)

queryClient.clear()

Expand All @@ -150,12 +160,9 @@ describe('PersistQueryClientProvider', () => {
queries: [
{
queryKey: key,
queryFn: async (): Promise<string> => {
await sleep(10)
return 'fetched'
},
queryFn: () => sleep(10).then(() => 'fetched'),
},
] as const,
],
}))

createEffect(() =>
Expand Down Expand Up @@ -183,9 +190,11 @@ describe('PersistQueryClientProvider', () => {
</PersistQueryClientProvider>
))

await waitFor(() => screen.getByText('fetchStatus: idle'))
await waitFor(() => screen.getByText('hydrated'))
await waitFor(() => screen.getByText('fetched'))
expect(screen.getByText('fetchStatus: idle')).toBeInTheDocument()
await vi.advanceTimersByTimeAsync(10)
expect(screen.getByText('hydrated')).toBeInTheDocument()
await vi.advanceTimersByTimeAsync(10)
expect(screen.getByText('fetched')).toBeInTheDocument()

expect(states).toHaveLength(3)

Expand Down Expand Up @@ -217,24 +226,23 @@ describe('PersistQueryClientProvider', () => {
}> = []

const queryClient = new QueryClient()
await queryClient.prefetchQuery({
queryClient.prefetchQuery({
queryKey: key,
queryFn: () => Promise.resolve('hydrated'),
queryFn: () => sleep(10).then(() => 'hydrated'),
})
await vi.advanceTimersByTimeAsync(10)

const persister = createMockPersister()

await persistQueryClientSave({ queryClient, persister })
persistQueryClientSave({ queryClient, persister })
await vi.advanceTimersByTimeAsync(0)

queryClient.clear()

function Page() {
const state = useQuery(() => ({
queryKey: key,
queryFn: async () => {
await sleep(10)
return 'fetched'
},
queryFn: () => sleep(10).then(() => 'fetched'),
initialData: 'initial',
// make sure that initial data is older than the hydration data
// otherwise initialData would be newer and takes precedence
Expand Down Expand Up @@ -266,9 +274,11 @@ describe('PersistQueryClientProvider', () => {
</PersistQueryClientProvider>
))

await waitFor(() => screen.getByText('initial'))
await waitFor(() => screen.getByText('hydrated'))
await waitFor(() => screen.getByText('fetched'))
expect(screen.getByText('initial')).toBeInTheDocument()
await vi.advanceTimersByTimeAsync(10)
expect(screen.getByText('hydrated')).toBeInTheDocument()
await vi.advanceTimersByTimeAsync(10)
expect(screen.getByText('fetched')).toBeInTheDocument()

expect(states).toHaveLength(3)

Expand Down Expand Up @@ -300,14 +310,16 @@ describe('PersistQueryClientProvider', () => {
}> = []

const queryClient = new QueryClient()
await queryClient.prefetchQuery({
queryClient.prefetchQuery({
queryKey: key,
queryFn: () => Promise.resolve('hydrated'),
queryFn: () => sleep(10).then(() => 'hydrated'),
})
await vi.advanceTimersByTimeAsync(10)

const persister = createMockPersister()

await persistQueryClientSave({ queryClient, persister })
persistQueryClientSave({ queryClient, persister })
await vi.advanceTimersByTimeAsync(0)

queryClient.clear()

Expand All @@ -316,11 +328,11 @@ describe('PersistQueryClientProvider', () => {
function Page() {
const state = useQuery(() => ({
queryKey: key,
queryFn: async () => {
fetched = true
await sleep(10)
return 'fetched'
},
queryFn: () =>
sleep(10).then(() => {
fetched = true
return 'fetched'
}),
staleTime: Infinity,
}))

Expand Down Expand Up @@ -349,13 +361,16 @@ describe('PersistQueryClientProvider', () => {
</PersistQueryClientProvider>
))

await waitFor(() => screen.getByText('data: null'))
await waitFor(() => screen.getByText('data: hydrated'))

expect(states).toHaveLength(2)
expect(screen.getByText('data: null')).toBeInTheDocument()
await vi.advanceTimersByTimeAsync(10)
expect(screen.getByText('data: hydrated')).toBeInTheDocument()
await vi.advanceTimersByTimeAsync(10)
expect(screen.getByText('data: hydrated')).toBeInTheDocument()

expect(fetched).toBe(false)

expect(states).toHaveLength(2)

expect(states[0]).toMatchObject({
status: 'pending',
fetchStatus: 'idle',
Expand All @@ -373,24 +388,23 @@ describe('PersistQueryClientProvider', () => {
const key = queryKey()

const queryClient = new QueryClient()
await queryClient.prefetchQuery({
queryClient.prefetchQuery({
queryKey: key,
queryFn: () => Promise.resolve('hydrated'),
queryFn: () => sleep(10).then(() => 'hydrated'),
})
await vi.advanceTimersByTimeAsync(10)

const persister = createMockPersister()

await persistQueryClientSave({ queryClient, persister })
persistQueryClientSave({ queryClient, persister })
await vi.advanceTimersByTimeAsync(0)

queryClient.clear()

function Page() {
const state = useQuery(() => ({
queryKey: key,
queryFn: async () => {
await sleep(10)
return 'fetched'
},
queryFn: () => sleep(10).then(() => 'fetched'),
}))

return (
Expand All @@ -412,11 +426,13 @@ describe('PersistQueryClientProvider', () => {
<Page />
</PersistQueryClientProvider>
))
expect(onSuccess).toHaveBeenCalledTimes(0)

await waitFor(() => screen.getByText('hydrated'))
expect(onSuccess).toHaveBeenCalledTimes(0)
await vi.advanceTimersByTimeAsync(10)
expect(screen.getByText('hydrated')).toBeInTheDocument()
expect(onSuccess).toHaveBeenCalledTimes(1)
await waitFor(() => screen.getByText('fetched'))
await vi.advanceTimersByTimeAsync(10)
expect(screen.getByText('fetched')).toBeInTheDocument()
})

test('should remove cache after non-successful restoring', async () => {
Expand All @@ -435,10 +451,7 @@ describe('PersistQueryClientProvider', () => {
function Page() {
const state = useQuery(() => ({
queryKey: key,
queryFn: async () => {
await sleep(10)
return 'fetched'
},
queryFn: () => sleep(10).then(() => 'fetched'),
}))

return (
Expand All @@ -460,10 +473,12 @@ describe('PersistQueryClientProvider', () => {
</PersistQueryClientProvider>
))

await waitFor(() => screen.getByText('fetched'))
await vi.advanceTimersByTimeAsync(10)
expect(removeClient).toHaveBeenCalledTimes(1)
expect(onSuccess).toHaveBeenCalledTimes(0)
expect(onError).toHaveBeenCalledTimes(1)
await vi.advanceTimersByTimeAsync(10)
expect(screen.getByText('fetched')).toBeInTheDocument()

expect(onErrorMock).toHaveBeenCalledTimes(1)
expect(onErrorMock).toHaveBeenNthCalledWith(1, error)
Expand All @@ -479,27 +494,27 @@ describe('PersistQueryClientProvider', () => {
}> = []

const queryClient = new QueryClient()
await queryClient.prefetchQuery({
queryClient.prefetchQuery({
queryKey: key,
queryFn: () => Promise.resolve('hydrated'),
queryFn: () => sleep(10).then(() => 'hydrated'),
})
await vi.advanceTimersByTimeAsync(10)

const persister = createMockPersister()

await persistQueryClientSave({ queryClient, persister })
persistQueryClientSave({ queryClient, persister })
await vi.advanceTimersByTimeAsync(0)

queryClient.clear()

const onSuccess = vi.fn()

const queryFn1 = vi.fn().mockImplementation(async () => {
await sleep(10)
return 'queryFn1'
})
const queryFn2 = vi.fn().mockImplementation(async () => {
await sleep(10)
return 'queryFn2'
})
const queryFn1 = vi
.fn()
.mockImplementation(() => sleep(10).then(() => 'queryFn1'))
const queryFn2 = vi
.fn()
.mockImplementation(() => sleep(10).then(() => 'queryFn2'))

function App() {
const [client, setClient] = createSignal(
Expand Down Expand Up @@ -556,8 +571,8 @@ describe('PersistQueryClientProvider', () => {

render(() => <App />)

await waitFor(() => screen.getByText('hydrated'))
await waitFor(() => screen.getByText('queryFn2'))
await vi.advanceTimersByTimeAsync(10)
expect(screen.getByText('queryFn2')).toBeInTheDocument()

expect(queryFn1).toHaveBeenCalledTimes(0)
expect(queryFn2).toHaveBeenCalledTimes(1)
Expand Down
Loading