diff --git a/packages/svelte-query-persist-client/tests/AwaitOnSuccess/AwaitOnSuccess.svelte b/packages/svelte-query-persist-client/tests/AwaitOnSuccess/AwaitOnSuccess.svelte index 02635f9b18..3e95c2416d 100644 --- a/packages/svelte-query-persist-client/tests/AwaitOnSuccess/AwaitOnSuccess.svelte +++ b/packages/svelte-query-persist-client/tests/AwaitOnSuccess/AwaitOnSuccess.svelte @@ -1,6 +1,5 @@
-

{data}

-

fetchStatus: {fetchStatus}

+

{$state.data}

+

fetchStatus: {$state.fetchStatus}

diff --git a/packages/svelte-query-persist-client/tests/FreshData/FreshData.svelte b/packages/svelte-query-persist-client/tests/FreshData/FreshData.svelte index 9e88b52645..d2a863c707 100644 --- a/packages/svelte-query-persist-client/tests/FreshData/FreshData.svelte +++ b/packages/svelte-query-persist-client/tests/FreshData/FreshData.svelte @@ -1,6 +1,5 @@
-

data: {data ?? 'null'}

-

fetchStatus: {fetchStatus}

+

data: {$state.data ?? 'null'}

+

fetchStatus: {$state.fetchStatus}

diff --git a/packages/svelte-query-persist-client/tests/InitialData/InitialData.svelte b/packages/svelte-query-persist-client/tests/InitialData/InitialData.svelte index b0cec48447..055dc5a433 100644 --- a/packages/svelte-query-persist-client/tests/InitialData/InitialData.svelte +++ b/packages/svelte-query-persist-client/tests/InitialData/InitialData.svelte @@ -1,6 +1,5 @@
-

{data}

-

fetchStatus: {fetchStatus}

+

{$state.data}

+

fetchStatus: {$state.fetchStatus}

diff --git a/packages/svelte-query-persist-client/tests/OnSuccess/OnSuccess.svelte b/packages/svelte-query-persist-client/tests/OnSuccess/OnSuccess.svelte index ab5b362965..335f44741a 100644 --- a/packages/svelte-query-persist-client/tests/OnSuccess/OnSuccess.svelte +++ b/packages/svelte-query-persist-client/tests/OnSuccess/OnSuccess.svelte @@ -1,6 +1,5 @@
-

{data}

-

fetchStatus: {fetchStatus}

+

{$state.data}

+

fetchStatus: {$state.fetchStatus}

diff --git a/packages/svelte-query-persist-client/tests/PersistQueryClientProvider.test.ts b/packages/svelte-query-persist-client/tests/PersistQueryClientProvider.test.ts index 8f438822e4..ab1bf7b515 100644 --- a/packages/svelte-query-persist-client/tests/PersistQueryClientProvider.test.ts +++ b/packages/svelte-query-persist-client/tests/PersistQueryClientProvider.test.ts @@ -57,7 +57,7 @@ const createMockErrorPersister = ( describe('PersistQueryClientProvider', () => { test('restores cache from persister', async () => { const key = queryKey() - const states: Writable>> = writable([]) + const statesStore: Writable>> = writable([]) const queryClient = createQueryClient() await queryClient.prefetchQuery({ @@ -76,7 +76,7 @@ describe('PersistQueryClientProvider', () => { queryClient, persistOptions: { persister }, key, - states, + states: statesStore, }, }) @@ -84,28 +84,28 @@ describe('PersistQueryClientProvider', () => { await waitFor(() => rendered.getByText('hydrated')) await waitFor(() => rendered.getByText('fetched')) - const states_ = get(states) - expect(states_).toHaveLength(4) + const states = get(statesStore) + expect(states).toHaveLength(4) - expect(states_[0]).toMatchObject({ + expect(states[0]).toMatchObject({ status: 'pending', fetchStatus: 'idle', data: undefined, }) - expect(states_[1]).toMatchObject({ + expect(states[1]).toMatchObject({ status: 'success', fetchStatus: 'fetching', data: 'hydrated', }) - expect(states_[2]).toMatchObject({ + expect(states[2]).toMatchObject({ status: 'success', fetchStatus: 'fetching', data: 'hydrated', }) - expect(states_[3]).toMatchObject({ + expect(states[3]).toMatchObject({ status: 'success', fetchStatus: 'idle', data: 'fetched', @@ -114,7 +114,7 @@ describe('PersistQueryClientProvider', () => { test('should also put useQueries into idle state', async () => { const key = queryKey() - const states: Writable>> = writable([]) + const statesStore: Writable>> = writable([]) const queryClient = createQueryClient() await queryClient.prefetchQuery({ @@ -133,7 +133,7 @@ describe('PersistQueryClientProvider', () => { queryClient, persistOptions: { persister }, key, - states, + states: statesStore, }, }) @@ -141,29 +141,29 @@ describe('PersistQueryClientProvider', () => { await waitFor(() => rendered.getByText('hydrated')) await waitFor(() => rendered.getByText('fetched')) - const states_ = get(states) + const states = get(statesStore) - expect(states_).toHaveLength(4) + expect(states).toHaveLength(4) - expect(states_[0]).toMatchObject({ + expect(states[0]).toMatchObject({ status: 'pending', fetchStatus: 'idle', data: undefined, }) - expect(states_[1]).toMatchObject({ + expect(states[1]).toMatchObject({ status: 'success', fetchStatus: 'fetching', data: 'hydrated', }) - expect(states_[2]).toMatchObject({ + expect(states[2]).toMatchObject({ status: 'success', fetchStatus: 'fetching', data: 'hydrated', }) - expect(states_[3]).toMatchObject({ + expect(states[3]).toMatchObject({ status: 'success', fetchStatus: 'idle', data: 'fetched', @@ -172,7 +172,7 @@ describe('PersistQueryClientProvider', () => { test('should show initialData while restoring', async () => { const key = queryKey() - const states: Writable>> = writable([]) + const statesStore: Writable>> = writable([]) const queryClient = createQueryClient() await queryClient.prefetchQuery({ @@ -191,7 +191,7 @@ describe('PersistQueryClientProvider', () => { queryClient, persistOptions: { persister }, key, - states, + states: statesStore, }, }) @@ -199,28 +199,28 @@ describe('PersistQueryClientProvider', () => { await waitFor(() => rendered.getByText('hydrated')) await waitFor(() => rendered.getByText('fetched')) - const states_ = get(states) - expect(states_).toHaveLength(4) + const states = get(statesStore) + expect(states).toHaveLength(4) - expect(states_[0]).toMatchObject({ + expect(states[0]).toMatchObject({ status: 'success', fetchStatus: 'idle', data: 'initial', }) - expect(states_[1]).toMatchObject({ + expect(states[1]).toMatchObject({ status: 'success', fetchStatus: 'fetching', data: 'hydrated', }) - expect(states_[2]).toMatchObject({ + expect(states[2]).toMatchObject({ status: 'success', fetchStatus: 'fetching', data: 'hydrated', }) - expect(states_[3]).toMatchObject({ + expect(states[3]).toMatchObject({ status: 'success', fetchStatus: 'idle', data: 'fetched', @@ -229,7 +229,7 @@ describe('PersistQueryClientProvider', () => { test('should not refetch after restoring when data is fresh', async () => { const key = queryKey() - const states: Writable>> = writable([]) + const statesStore: Writable>> = writable([]) const queryClient = createQueryClient() await queryClient.prefetchQuery({ @@ -250,7 +250,7 @@ describe('PersistQueryClientProvider', () => { queryClient, persistOptions: { persister }, key, - states, + states: statesStore, fetched, }, }) @@ -258,18 +258,18 @@ describe('PersistQueryClientProvider', () => { await waitFor(() => rendered.getByText('data: null')) await waitFor(() => rendered.getByText('data: hydrated')) - const states_ = get(states) - expect(states_).toHaveLength(2) + const states = get(statesStore) + expect(states).toHaveLength(2) expect(get(fetched)).toBe(false) - expect(states_[0]).toMatchObject({ + expect(states[0]).toMatchObject({ status: 'pending', fetchStatus: 'idle', data: undefined, }) - expect(states_[1]).toMatchObject({ + expect(states[1]).toMatchObject({ status: 'success', fetchStatus: 'idle', data: 'hydrated', @@ -324,25 +324,28 @@ describe('PersistQueryClientProvider', () => { queryClient.clear() - const states: Writable> = writable([]) + const statesStore: Writable> = writable([]) const rendered = render(AwaitOnSuccess, { props: { queryClient, persistOptions: { persister }, key, - states, + states: statesStore, onSuccess: async () => { - states.update((s) => [...s, 'onSuccess']) + statesStore.update((s) => [...s, 'onSuccess']) await sleep(20) - states.update((s) => [...s, 'onSuccess done']) + statesStore.update((s) => [...s, 'onSuccess done']) }, }, }) await waitFor(() => rendered.getByText('hydrated')) await waitFor(() => rendered.getByText('fetched')) - expect(get(states)).toEqual([ + + const states = get(statesStore) + + expect(states).toEqual([ 'onSuccess', 'onSuccess done', 'fetching', diff --git a/packages/svelte-query-persist-client/tests/RemoveCache/RemoveCache.svelte b/packages/svelte-query-persist-client/tests/RemoveCache/RemoveCache.svelte index ab5b362965..335f44741a 100644 --- a/packages/svelte-query-persist-client/tests/RemoveCache/RemoveCache.svelte +++ b/packages/svelte-query-persist-client/tests/RemoveCache/RemoveCache.svelte @@ -1,6 +1,5 @@
-

{data}

-

fetchStatus: {fetchStatus}

+

{$state.data}

+

fetchStatus: {$state.fetchStatus}

diff --git a/packages/svelte-query-persist-client/tests/RestoreCache/RestoreCache.svelte b/packages/svelte-query-persist-client/tests/RestoreCache/RestoreCache.svelte index 40f77e244d..5122413166 100644 --- a/packages/svelte-query-persist-client/tests/RestoreCache/RestoreCache.svelte +++ b/packages/svelte-query-persist-client/tests/RestoreCache/RestoreCache.svelte @@ -1,6 +1,5 @@
-

{data}

-

fetchStatus: {fetchStatus}

+

{$state.data}

+

fetchStatus: {$state.fetchStatus}

diff --git a/packages/svelte-query-persist-client/tests/UseQueries/UseQueries.svelte b/packages/svelte-query-persist-client/tests/UseQueries/UseQueries.svelte index 8895bc59e4..70ef9aceab 100644 --- a/packages/svelte-query-persist-client/tests/UseQueries/UseQueries.svelte +++ b/packages/svelte-query-persist-client/tests/UseQueries/UseQueries.svelte @@ -1,6 +1,5 @@
-

{data}

-

fetchStatus: {fetchStatus}

+

{$state[0].data}

+

fetchStatus: {$state[0].fetchStatus}

diff --git a/packages/svelte-query/tests/createQueries/BaseExample.svelte b/packages/svelte-query/tests/createQueries/BaseExample.svelte index bb2fe5a846..6401f34b10 100644 --- a/packages/svelte-query/tests/createQueries/BaseExample.svelte +++ b/packages/svelte-query/tests/createQueries/BaseExample.svelte @@ -15,13 +15,13 @@ {#if Array.isArray($queries)} {#each $queries as query, index} {#if query.isPending} -

Loading {index + 1}

+
Loading {index + 1}
{:else if query.isSuccess} -

{query.data}

+
{query.data}
{/if} {/each} {:else if $queries.isPending} -

Loading

+
Loading
{:else if $queries.isSuccess} -

{$queries.data}

+
{$queries.data}
{/if} diff --git a/packages/svelte-query/tests/createQuery/BaseExample.svelte b/packages/svelte-query/tests/createQuery/BaseExample.svelte index e95b54d901..ede107bcdd 100644 --- a/packages/svelte-query/tests/createQuery/BaseExample.svelte +++ b/packages/svelte-query/tests/createQuery/BaseExample.svelte @@ -1,24 +1,25 @@ +
Status: {$query.status}
+
Failure Count: {$query.failureCount}
+ {#if $query.isPending} -

Loading

+
Loading
{:else if $query.isError} -

Error

+
Error
{:else if $query.isSuccess} - {#if Array.isArray($query.data)} - {#each $query.data as item} -

{item}

- {/each} - {:else} -

{$query.data}

- {/if} +
{$query.data}
{/if} diff --git a/packages/svelte-query/tests/createQuery/PlaceholderData.svelte b/packages/svelte-query/tests/createQuery/PlaceholderData.svelte new file mode 100644 index 0000000000..b56fd40e78 --- /dev/null +++ b/packages/svelte-query/tests/createQuery/PlaceholderData.svelte @@ -0,0 +1,30 @@ + + + + +
Status: {$query.status}
+
Data: {$query.data}
diff --git a/packages/svelte-query/tests/createQuery/createQuery.test.ts b/packages/svelte-query/tests/createQuery/createQuery.test.ts index 0449eb951c..d1c6d7b5a4 100644 --- a/packages/svelte-query/tests/createQuery/createQuery.test.ts +++ b/packages/svelte-query/tests/createQuery/createQuery.test.ts @@ -1,36 +1,206 @@ import { describe, expect, test } from 'vitest' import { fireEvent, render, waitFor } from '@testing-library/svelte' -import { derived, writable } from 'svelte/store' +import { derived, get, writable } from 'svelte/store' import { QueryClient } from '@tanstack/query-core' import { sleep } from '../utils' import BaseExample from './BaseExample.svelte' import DisabledExample from './DisabledExample.svelte' +import PlaceholderData from './PlaceholderData.svelte' +import type { Writable } from 'svelte/store' +import type { QueryObserverResult } from '@tanstack/query-core' describe('createQuery', () => { - test('Render and wait for success', async () => { + test('Return the correct states for a successful query', async () => { + const statesStore: Writable> = writable([]) + + const options = { + queryKey: ['test'], + queryFn: async () => { + await sleep(10) + return 'Success' + }, + } + const rendered = render(BaseExample, { props: { - options: { - queryKey: ['test'], - queryFn: async () => { - await sleep(10) - return 'Success' - }, - }, + options, queryClient: new QueryClient(), + states: statesStore, }, }) await waitFor(() => { - expect(rendered.queryByText('Loading')).toBeInTheDocument() + expect(rendered.queryByText('Success')).toBeInTheDocument() }) - await waitFor(() => { - expect(rendered.queryByText('Success')).toBeInTheDocument() + const states = get(statesStore) + + expect(states).toHaveLength(2) + + expect(states[0]).toMatchObject({ + data: undefined, + dataUpdatedAt: 0, + error: null, + errorUpdatedAt: 0, + failureCount: 0, + failureReason: null, + errorUpdateCount: 0, + isError: false, + isFetched: false, + isFetchedAfterMount: false, + isFetching: true, + isPaused: false, + isPending: true, + isInitialLoading: true, + isLoading: true, + isLoadingError: false, + isPlaceholderData: false, + isRefetchError: false, + isRefetching: false, + isStale: true, + isSuccess: false, + refetch: expect.any(Function), + status: 'pending', + fetchStatus: 'fetching', + }) + + expect(states[1]).toMatchObject({ + data: 'Success', + dataUpdatedAt: expect.any(Number), + error: null, + errorUpdatedAt: 0, + failureCount: 0, + failureReason: null, + errorUpdateCount: 0, + isError: false, + isFetched: true, + isFetchedAfterMount: true, + isFetching: false, + isPaused: false, + isPending: false, + isInitialLoading: false, + isLoading: false, + isLoadingError: false, + isPlaceholderData: false, + isRefetchError: false, + isRefetching: false, + isStale: true, + isSuccess: true, + refetch: expect.any(Function), + status: 'success', + fetchStatus: 'idle', + }) + }) + + test('Return the correct states for an unsuccessful query', async () => { + const statesStore: Writable> = writable([]) + + const options = { + queryKey: ['test'], + queryFn: async () => Promise.reject(new Error('Rejected')), + retry: 1, + retryDelay: 1, + } + + const rendered = render(BaseExample, { + props: { + options, + queryClient: new QueryClient(), + states: statesStore, + }, + }) + + await waitFor(() => rendered.getByText('Status: error')) + + const states = get(statesStore) + + expect(states).toHaveLength(3) + + expect(states[0]).toMatchObject({ + data: undefined, + dataUpdatedAt: 0, + error: null, + errorUpdatedAt: 0, + failureCount: 0, + failureReason: null, + errorUpdateCount: 0, + isError: false, + isFetched: false, + isFetchedAfterMount: false, + isFetching: true, + isPaused: false, + isPending: true, + isInitialLoading: true, + isLoading: true, + isLoadingError: false, + isPlaceholderData: false, + isRefetchError: false, + isRefetching: false, + isStale: true, + isSuccess: false, + refetch: expect.any(Function), + status: 'pending', + fetchStatus: 'fetching', + }) + + expect(states[1]).toMatchObject({ + data: undefined, + dataUpdatedAt: 0, + error: null, + errorUpdatedAt: 0, + failureCount: 1, + failureReason: new Error('Rejected'), + errorUpdateCount: 0, + isError: false, + isFetched: false, + isFetchedAfterMount: false, + isFetching: true, + isPaused: false, + isPending: true, + isInitialLoading: true, + isLoading: true, + isLoadingError: false, + isPlaceholderData: false, + isRefetchError: false, + isRefetching: false, + isStale: true, + isSuccess: false, + refetch: expect.any(Function), + status: 'pending', + fetchStatus: 'fetching', + }) + + expect(states[2]).toMatchObject({ + data: undefined, + dataUpdatedAt: 0, + error: new Error('Rejected'), + errorUpdatedAt: expect.any(Number), + failureCount: 2, + failureReason: new Error('Rejected'), + errorUpdateCount: 1, + isError: true, + isFetched: true, + isFetchedAfterMount: true, + isFetching: false, + isPaused: false, + isPending: false, + isInitialLoading: false, + isLoading: false, + isLoadingError: true, + isPlaceholderData: false, + isRefetchError: false, + isRefetching: false, + isStale: true, + isSuccess: false, + refetch: expect.any(Function), + status: 'error', + fetchStatus: 'idle', }) }) test('Accept a writable store for options', async () => { + const statesStore: Writable> = writable([]) + const optionsStore = writable({ queryKey: ['test'], queryFn: async () => { @@ -43,6 +213,7 @@ describe('createQuery', () => { props: { options: optionsStore, queryClient: new QueryClient(), + states: statesStore, }, }) @@ -52,6 +223,8 @@ describe('createQuery', () => { }) test('Accept a derived store for options', async () => { + const statesStore: Writable> = writable([]) + const writableStore = writable('test') const derivedStore = derived(writableStore, ($store) => ({ @@ -66,6 +239,7 @@ describe('createQuery', () => { props: { options: derivedStore, queryClient: new QueryClient(), + states: statesStore, }, }) @@ -75,6 +249,8 @@ describe('createQuery', () => { }) test('Ensure reactivity when queryClient defaults are set', async () => { + const statesStore: Writable> = writable([]) + const writableStore = writable(1) const derivedStore = derived(writableStore, ($store) => ({ @@ -91,6 +267,7 @@ describe('createQuery', () => { queryClient: new QueryClient({ defaultOptions: { queries: { staleTime: 60 * 1000 } }, }), + states: statesStore, }, }) @@ -114,45 +291,53 @@ describe('createQuery', () => { }) }) - test('Keep previous data when returned as placeholder data', async () => { - const writableStore = writable>([1]) - - const derivedStore = derived(writableStore, ($store) => ({ - queryKey: ['test', $store], - queryFn: async () => { - await sleep(10) - return $store.map((id) => `Success ${id}`) - }, - placeholderData: (previousData: string) => previousData, - })) + test('Keep previous data when placeholderData is set', async () => { + const statesStore: Writable> = writable([]) - const rendered = render(BaseExample, { + const rendered = render(PlaceholderData, { props: { - options: derivedStore, queryClient: new QueryClient(), + states: statesStore, }, }) - await waitFor(() => { - expect(rendered.queryByText('Success 1')).not.toBeInTheDocument() - expect(rendered.queryByText('Success 2')).not.toBeInTheDocument() - }) + await waitFor(() => rendered.getByText('Data: 0')) - await waitFor(() => { - expect(rendered.queryByText('Success 1')).toBeInTheDocument() - expect(rendered.queryByText('Success 2')).not.toBeInTheDocument() - }) + fireEvent.click(rendered.getByRole('button', { name: 'setCount' })) - writableStore.set([1, 2]) + await waitFor(() => rendered.getByText('Data: 1')) - await waitFor(() => { - expect(rendered.queryByText('Success 1')).toBeInTheDocument() - expect(rendered.queryByText('Success 2')).not.toBeInTheDocument() - }) + const states = get(statesStore) - await waitFor(() => { - expect(rendered.queryByText('Success 1')).toBeInTheDocument() - expect(rendered.queryByText('Success 2')).toBeInTheDocument() + expect(states).toHaveLength(4) + + // Initial + expect(states[0]).toMatchObject({ + data: undefined, + isFetching: true, + isSuccess: false, + isPlaceholderData: false, + }) + // Fetched + expect(states[1]).toMatchObject({ + data: 0, + isFetching: false, + isSuccess: true, + isPlaceholderData: false, + }) + // Set state + expect(states[2]).toMatchObject({ + data: 0, + isFetching: true, + isSuccess: true, + isPlaceholderData: true, + }) + // New data + expect(states[3]).toMatchObject({ + data: 1, + isFetching: false, + isSuccess: true, + isPlaceholderData: false, }) })