diff --git a/src/core/mutation.ts b/src/core/mutation.ts index 6d303b91bc..f8cecc5d3d 100644 --- a/src/core/mutation.ts +++ b/src/core/mutation.ts @@ -186,8 +186,33 @@ export class Mutation< }) } + const executeMutation = () => { + this.retryer = createRetryer({ + fn: () => { + if (!this.options.mutationFn) { + return Promise.reject('No mutationFn found') + } + return this.options.mutationFn(this.state.variables!) + }, + onFail: () => { + this.dispatch({ type: 'failed' }) + }, + onPause: () => { + this.dispatch({ type: 'pause' }) + }, + onContinue: () => { + this.dispatch({ type: 'continue' }) + }, + retry: this.options.retry ?? 0, + retryDelay: this.options.retryDelay, + networkMode: this.options.networkMode, + }) + + return this.retryer.promise + } + return promise - .then(() => this.executeMutation()) + .then(executeMutation) .then(result => { data = result // Notify cache callback @@ -253,33 +278,61 @@ export class Mutation< }) } - private executeMutation(): Promise { - this.retryer = createRetryer({ - fn: () => { - if (!this.options.mutationFn) { - return Promise.reject('No mutationFn found') - } - return this.options.mutationFn(this.state.variables!) - }, - onFail: () => { - this.dispatch({ type: 'failed' }) - }, - onPause: () => { - this.dispatch({ type: 'pause' }) - }, - onContinue: () => { - this.dispatch({ type: 'continue' }) - }, - retry: this.options.retry ?? 0, - retryDelay: this.options.retryDelay, - networkMode: this.options.networkMode, - }) - - return this.retryer.promise - } - private dispatch(action: Action): void { - this.state = this.reducer(action) + const reducer = ( + state: MutationState + ): MutationState => { + switch (action.type) { + case 'failed': + return { + ...state, + failureCount: state.failureCount + 1, + } + case 'pause': + return { + ...state, + isPaused: true, + } + case 'continue': + return { + ...state, + isPaused: false, + } + case 'loading': + return { + ...state, + context: action.context, + data: undefined, + error: null, + isPaused: !canFetch(this.options.networkMode), + status: 'loading', + variables: action.variables, + } + case 'success': + return { + ...state, + data: action.data, + error: null, + status: 'success', + isPaused: false, + } + case 'error': + return { + ...state, + data: undefined, + error: action.error, + failureCount: state.failureCount + 1, + isPaused: false, + status: 'error', + } + case 'setState': + return { + ...state, + ...action.state, + } + } + } + this.state = reducer(this.state) notifyManager.batch(() => { this.observers.forEach(observer => { @@ -292,62 +345,6 @@ export class Mutation< }) }) } - - private reducer( - action: Action - ): MutationState { - switch (action.type) { - case 'failed': - return { - ...this.state, - failureCount: this.state.failureCount + 1, - } - case 'pause': - return { - ...this.state, - isPaused: true, - } - case 'continue': - return { - ...this.state, - isPaused: false, - } - case 'loading': - return { - ...this.state, - context: action.context, - data: undefined, - error: null, - isPaused: !canFetch(this.options.networkMode), - status: 'loading', - variables: action.variables, - } - case 'success': - return { - ...this.state, - data: action.data, - error: null, - status: 'success', - isPaused: false, - } - case 'error': - return { - ...this.state, - data: undefined, - error: action.error, - failureCount: this.state.failureCount + 1, - isPaused: false, - status: 'error', - } - case 'setState': - return { - ...this.state, - ...action.state, - } - default: - return this.state - } - } } export function getDefaultState< diff --git a/src/core/mutationCache.ts b/src/core/mutationCache.ts index a101013d3f..91eb0ac9b9 100644 --- a/src/core/mutationCache.ts +++ b/src/core/mutationCache.ts @@ -143,14 +143,6 @@ export class MutationCache extends Subscribable { }) } - onFocus(): void { - this.resumePausedMutations() - } - - onOnline(): void { - this.resumePausedMutations() - } - resumePausedMutations(): Promise { const pausedMutations = this.mutations.filter(x => x.state.isPaused) return notifyManager.batch(() => diff --git a/src/core/queriesObserver.ts b/src/core/queriesObserver.ts index 79d1bbc168..a582a703a0 100644 --- a/src/core/queriesObserver.ts +++ b/src/core/queriesObserver.ts @@ -60,7 +60,52 @@ export class QueriesObserver extends Subscribable { notifyOptions?: NotifyOptions ): void { this.queries = queries - this.updateObservers(notifyOptions) + + notifyManager.batch(() => { + const prevObservers = this.observers + + const newObserverMatches = this.findMatchingObservers(this.queries) + + // set options for the new observers to notify of changes + newObserverMatches.forEach(match => + match.observer.setOptions(match.defaultedQueryOptions, notifyOptions) + ) + + const newObservers = newObserverMatches.map(match => match.observer) + const newObserversMap = Object.fromEntries( + newObservers.map(observer => [observer.options.queryHash, observer]) + ) + const newResult = newObservers.map(observer => + observer.getCurrentResult() + ) + + const hasIndexChange = newObservers.some( + (observer, index) => observer !== prevObservers[index] + ) + if (prevObservers.length === newObservers.length && !hasIndexChange) { + return + } + + this.observers = newObservers + this.observersMap = newObserversMap + this.result = newResult + + if (!this.hasListeners()) { + return + } + + difference(prevObservers, newObservers).forEach(observer => { + observer.destroy() + }) + + difference(newObservers, prevObservers).forEach(observer => { + observer.subscribe(result => { + this.onUpdate(observer, result) + }) + }) + + this.notify() + }) } getCurrentResult(): QueryObserverResult[] { @@ -106,6 +151,12 @@ export class QueriesObserver extends Subscribable { !matchingObservers.some(match => match.observer === prevObserver) ) + const getObserver = (options: QueryObserverOptions): QueryObserver => { + const defaultedOptions = this.client.defaultQueryOptions(options) + const currentObserver = this.observersMap[defaultedOptions.queryHash!] + return currentObserver ?? new QueryObserver(this.client, defaultedOptions) + } + const newOrReusedObservers: QueryObserverMatch[] = unmatchedQueries.map( (options, index) => { if (options.keepPreviousData) { @@ -120,7 +171,7 @@ export class QueriesObserver extends Subscribable { } return { defaultedQueryOptions: options, - observer: this.getObserver(options), + observer: getObserver(options), } } ) @@ -137,60 +188,6 @@ export class QueriesObserver extends Subscribable { .sort(sortMatchesByOrderOfQueries) } - private getObserver(options: QueryObserverOptions): QueryObserver { - const defaultedOptions = this.client.defaultQueryOptions(options) - const currentObserver = this.observersMap[defaultedOptions.queryHash!] - return currentObserver ?? new QueryObserver(this.client, defaultedOptions) - } - - private updateObservers(notifyOptions?: NotifyOptions): void { - notifyManager.batch(() => { - const prevObservers = this.observers - - const newObserverMatches = this.findMatchingObservers(this.queries) - - // set options for the new observers to notify of changes - newObserverMatches.forEach(match => - match.observer.setOptions(match.defaultedQueryOptions, notifyOptions) - ) - - const newObservers = newObserverMatches.map(match => match.observer) - const newObserversMap = Object.fromEntries( - newObservers.map(observer => [observer.options.queryHash, observer]) - ) - const newResult = newObservers.map(observer => - observer.getCurrentResult() - ) - - const hasIndexChange = newObservers.some( - (observer, index) => observer !== prevObservers[index] - ) - if (prevObservers.length === newObservers.length && !hasIndexChange) { - return - } - - this.observers = newObservers - this.observersMap = newObserversMap - this.result = newResult - - if (!this.hasListeners()) { - return - } - - difference(prevObservers, newObservers).forEach(observer => { - observer.destroy() - }) - - difference(newObservers, prevObservers).forEach(observer => { - observer.subscribe(result => { - this.onUpdate(observer, result) - }) - }) - - this.notify() - }) - } - private onUpdate(observer: QueryObserver, result: QueryObserverResult): void { const index = this.observers.indexOf(observer) if (index !== -1) { diff --git a/src/core/query.ts b/src/core/query.ts index be087dbbea..8832272818 100644 --- a/src/core/query.ts +++ b/src/core/query.ts @@ -171,7 +171,7 @@ export class Query< this.cache = config.cache this.queryKey = config.queryKey this.queryHash = config.queryHash - this.initialState = config.state || this.getDefaultState(this.options) + this.initialState = config.state || getDefaultState(this.options) this.state = this.initialState this.meta = config.meta } @@ -500,7 +500,80 @@ export class Query< } private dispatch(action: Action): void { - this.state = this.reducer(this.state, action) + const reducer = ( + state: QueryState + ): QueryState => { + switch (action.type) { + case 'failed': + return { + ...state, + fetchFailureCount: state.fetchFailureCount + 1, + } + case 'pause': + return { + ...state, + fetchStatus: 'paused', + } + case 'continue': + return { + ...state, + fetchStatus: 'fetching', + } + case 'fetch': + return { + ...state, + fetchFailureCount: 0, + fetchMeta: action.meta ?? null, + fetchStatus: canFetch(this.options.networkMode) + ? 'fetching' + : 'paused', + ...(!state.dataUpdatedAt && { + error: null, + status: 'loading', + }), + } + case 'success': + return { + ...state, + data: action.data, + dataUpdateCount: state.dataUpdateCount + 1, + dataUpdatedAt: action.dataUpdatedAt ?? Date.now(), + error: null, + fetchFailureCount: 0, + isInvalidated: false, + fetchStatus: 'idle', + status: 'success', + } + case 'error': + const error = action.error as unknown + + if (isCancelledError(error) && error.revert && this.revertState) { + return { ...this.revertState } + } + + return { + ...state, + error: error as TError, + errorUpdateCount: state.errorUpdateCount + 1, + errorUpdatedAt: Date.now(), + fetchFailureCount: state.fetchFailureCount + 1, + fetchStatus: 'idle', + status: 'error', + } + case 'invalidate': + return { + ...state, + isInvalidated: true, + } + case 'setState': + return { + ...state, + ...action.state, + } + } + } + + this.state = reducer(this.state) notifyManager.batch(() => { this.observers.forEach(observer => { @@ -510,113 +583,42 @@ export class Query< this.cache.notify({ query: this, type: 'updated', action }) }) } +} - protected getDefaultState( - options: QueryOptions - ): QueryState { - const data = - typeof options.initialData === 'function' - ? (options.initialData as InitialDataFunction)() - : options.initialData - - const hasInitialData = typeof options.initialData !== 'undefined' - - const initialDataUpdatedAt = hasInitialData - ? typeof options.initialDataUpdatedAt === 'function' - ? (options.initialDataUpdatedAt as () => number | undefined)() - : options.initialDataUpdatedAt - : 0 - - const hasData = typeof data !== 'undefined' - - return { - data, - dataUpdateCount: 0, - dataUpdatedAt: hasData ? initialDataUpdatedAt ?? Date.now() : 0, - error: null, - errorUpdateCount: 0, - errorUpdatedAt: 0, - fetchFailureCount: 0, - fetchMeta: null, - isInvalidated: false, - status: hasData ? 'success' : 'idle', - fetchStatus: 'idle', - } - } - - protected reducer( - state: QueryState, - action: Action - ): QueryState { - switch (action.type) { - case 'failed': - return { - ...state, - fetchFailureCount: state.fetchFailureCount + 1, - } - case 'pause': - return { - ...state, - fetchStatus: 'paused', - } - case 'continue': - return { - ...state, - fetchStatus: 'fetching', - } - case 'fetch': - return { - ...state, - fetchFailureCount: 0, - fetchMeta: action.meta ?? null, - fetchStatus: canFetch(this.options.networkMode) - ? 'fetching' - : 'paused', - ...(!state.dataUpdatedAt && { - error: null, - status: 'loading', - }), - } - case 'success': - return { - ...state, - data: action.data, - dataUpdateCount: state.dataUpdateCount + 1, - dataUpdatedAt: action.dataUpdatedAt ?? Date.now(), - error: null, - fetchFailureCount: 0, - isInvalidated: false, - fetchStatus: 'idle', - status: 'success', - } - case 'error': - const error = action.error as unknown - - if (isCancelledError(error) && error.revert && this.revertState) { - return { ...this.revertState } - } - - return { - ...state, - error: error as TError, - errorUpdateCount: state.errorUpdateCount + 1, - errorUpdatedAt: Date.now(), - fetchFailureCount: state.fetchFailureCount + 1, - fetchStatus: 'idle', - status: 'error', - } - case 'invalidate': - return { - ...state, - isInvalidated: true, - } - case 'setState': - return { - ...state, - ...action.state, - } - default: - return state - } +function getDefaultState< + TQueryFnData, + TError, + TData, + TQueryKey extends QueryKey +>( + options: QueryOptions +): QueryState { + const data = + typeof options.initialData === 'function' + ? (options.initialData as InitialDataFunction)() + : options.initialData + + const hasInitialData = typeof options.initialData !== 'undefined' + + const initialDataUpdatedAt = hasInitialData + ? typeof options.initialDataUpdatedAt === 'function' + ? (options.initialDataUpdatedAt as () => number | undefined)() + : options.initialDataUpdatedAt + : 0 + + const hasData = typeof data !== 'undefined' + + return { + data, + dataUpdateCount: 0, + dataUpdatedAt: hasData ? initialDataUpdatedAt ?? Date.now() : 0, + error: null, + errorUpdateCount: 0, + errorUpdatedAt: 0, + fetchFailureCount: 0, + fetchMeta: null, + isInvalidated: false, + status: hasData ? 'success' : 'idle', + fetchStatus: 'idle', } } diff --git a/src/core/queryClient.ts b/src/core/queryClient.ts index 589b723504..af0cf460af 100644 --- a/src/core/queryClient.ts +++ b/src/core/queryClient.ts @@ -75,13 +75,13 @@ export class QueryClient { mount(): void { this.unsubscribeFocus = focusManager.subscribe(() => { if (focusManager.isFocused()) { - this.mutationCache.onFocus() + this.resumePausedMutations() this.queryCache.onFocus() } }) this.unsubscribeOnline = onlineManager.subscribe(() => { if (onlineManager.isOnline()) { - this.mutationCache.onOnline() + this.resumePausedMutations() this.queryCache.onOnline() } }) @@ -509,7 +509,7 @@ export class QueryClient { } resumePausedMutations(): Promise { - return this.getMutationCache().resumePausedMutations() + return this.mutationCache.resumePausedMutations() } getQueryCache(): QueryCache { diff --git a/src/core/queryObserver.ts b/src/core/queryObserver.ts index 9dacf75669..7cf4c28965 100644 --- a/src/core/queryObserver.ts +++ b/src/core/queryObserver.ts @@ -16,7 +16,6 @@ import type { QueryObserverResult, QueryOptions, RefetchOptions, - ResultOptions, } from './types' import type { Query, QueryState, Action, FetchOptions } from './query' import type { QueryClient } from './queryClient' @@ -131,7 +130,8 @@ export class QueryObserver< destroy(): void { this.listeners = [] - this.clearTimers() + this.clearStaleTimeout() + this.clearRefetchInterval() this.currentQuery.removeObserver(this) } @@ -246,23 +246,6 @@ export class QueryObserver< return trackedResult } - getNextResult( - options?: ResultOptions - ): Promise> { - return new Promise((resolve, reject) => { - const unsubscribe = this.subscribe(result => { - if (!result.isFetching) { - unsubscribe() - if (result.isError && options?.throwOnError) { - reject(result.error) - } else { - resolve(result) - } - } - }) - }) - } - getCurrentQuery(): Query { return this.currentQuery } @@ -395,11 +378,6 @@ export class QueryObserver< this.updateRefetchInterval(this.computeRefetchInterval()) } - private clearTimers(): void { - this.clearStaleTimeout() - this.clearRefetchInterval() - } - private clearStaleTimeout(): void { clearTimeout(this.staleTimeoutId!) this.staleTimeoutId = undefined @@ -588,36 +566,6 @@ export class QueryObserver< return result as QueryObserverResult } - private shouldNotifyListeners( - result: QueryObserverResult, - prevResult?: QueryObserverResult - ): boolean { - if (!prevResult) { - return true - } - - const { notifyOnChangeProps } = this.options - - if ( - notifyOnChangeProps === 'all' || - (!notifyOnChangeProps && !this.trackedProps.size) - ) { - return true - } - - const includedProps = new Set(notifyOnChangeProps ?? this.trackedProps) - - if (this.options.useErrorBoundary) { - includedProps.add('error') - } - - return Object.keys(result).some(key => { - const typedKey = key as keyof QueryObserverResult - const changed = result[typedKey] !== prevResult[typedKey] - return changed && includedProps.has(typedKey) - }) - } - updateResult(notifyOptions?: NotifyOptions): void { const prevResult = this.currentResult as | QueryObserverResult @@ -635,10 +583,34 @@ export class QueryObserver< // Determine which callbacks to trigger const defaultNotifyOptions: NotifyOptions = { cache: true } - if ( - notifyOptions?.listeners !== false && - this.shouldNotifyListeners(this.currentResult, prevResult) - ) { + const shouldNotifyListeners = (): boolean => { + if (!prevResult) { + return true + } + + const { notifyOnChangeProps } = this.options + + if ( + notifyOnChangeProps === 'all' || + (!notifyOnChangeProps && !this.trackedProps.size) + ) { + return true + } + + const includedProps = new Set(notifyOnChangeProps ?? this.trackedProps) + + if (this.options.useErrorBoundary) { + includedProps.add('error') + } + + return Object.keys(this.currentResult).some(key => { + const typedKey = key as keyof QueryObserverResult + const changed = this.currentResult[typedKey] !== prevResult[typedKey] + return changed && includedProps.has(typedKey) + }) + } + + if (notifyOptions?.listeners !== false && shouldNotifyListeners()) { defaultNotifyOptions.listeners = true } diff --git a/src/core/tests/mutations.test.tsx b/src/core/tests/mutations.test.tsx index 8f624ad64e..71e491bdea 100644 --- a/src/core/tests/mutations.test.tsx +++ b/src/core/tests/mutations.test.tsx @@ -368,28 +368,4 @@ describe('mutations', () => { consoleMock.mockRestore() }) - - test('reducer should return the state for an unknown action type', async () => { - const observer = new MutationObserver(queryClient, { - mutationKey: ['key'], - mutationFn: async () => 'data', - }) - - const spy = jest.fn() - const unsubscribe = observer.subscribe(spy) - observer.mutate() - const mutation = queryClient - .getMutationCache() - .find({ mutationKey: ['key'] })! - const prevState = observer.getCurrentResult() - spy.mockReset() - - // Force dispatch unknown action type - // because no use case has been found - //@ts-expect-error - mutation.dispatch({ type: 'unknown' }) - expect(spy).toHaveBeenCalledWith(prevState) - - unsubscribe() - }) }) diff --git a/src/core/tests/queriesObserver.test.tsx b/src/core/tests/queriesObserver.test.tsx index 27c1d0fdfd..8345a2a63c 100644 --- a/src/core/tests/queriesObserver.test.tsx +++ b/src/core/tests/queriesObserver.test.tsx @@ -255,8 +255,8 @@ describe('queriesObserver', () => { test('should trigger all fetches when subscribed', async () => { const key1 = queryKey() const key2 = queryKey() - const queryFn1 = jest.fn() - const queryFn2 = jest.fn() + const queryFn1 = jest.fn().mockReturnValue(1) + const queryFn2 = jest.fn().mockReturnValue(2) const observer = new QueriesObserver(queryClient, [ { queryKey: key1, queryFn: queryFn1 }, { queryKey: key2, queryFn: queryFn2 }, diff --git a/src/core/tests/query.test.tsx b/src/core/tests/query.test.tsx index b5aefa4b14..1fdee7d1ff 100644 --- a/src/core/tests/query.test.tsx +++ b/src/core/tests/query.test.tsx @@ -711,18 +711,6 @@ describe('query', () => { query['dispatch'] = dispatchOriginal }) - test('reducer should return the state for an unknown action type', async () => { - const key = queryKey() - - await queryClient.prefetchQuery(key, () => 'data') - const query = queryCache.find(key)! - - // Force unknown action type - //@ts-expect-error - const reducedState = query['reducer'](query.state, { type: 'unknown' }) - expect(reducedState).toEqual(query.state) - }) - test('fetch should not dispatch "fetch" if state meta and fetchOptions meta are the same object', async () => { const key = queryKey() diff --git a/src/core/tests/queryClient.test.tsx b/src/core/tests/queryClient.test.tsx index 0d60ff4206..1ed9de02ef 100644 --- a/src/core/tests/queryClient.test.tsx +++ b/src/core/tests/queryClient.test.tsx @@ -863,7 +863,7 @@ describe('queryClient', () => { describe('refetchQueries', () => { test('should not refetch if all observers are disabled', async () => { const key = queryKey() - const queryFn = jest.fn() + const queryFn = jest.fn().mockReturnValue('data') await queryClient.fetchQuery(key, queryFn) const observer1 = new QueryObserver(queryClient, { queryKey: key, @@ -877,7 +877,7 @@ describe('queryClient', () => { }) test('should refetch if at least one observer is enabled', async () => { const key = queryKey() - const queryFn = jest.fn() + const queryFn = jest.fn().mockReturnValue('data') await queryClient.fetchQuery(key, queryFn) const observer1 = new QueryObserver(queryClient, { queryKey: key, @@ -1424,30 +1424,25 @@ describe('queryClient', () => { testClient.getQueryCache(), 'onOnline' ) - const mutationCacheOnFocusSpy = jest.spyOn( + const mutationCacheResumePausedMutationsSpy = jest.spyOn( testClient.getMutationCache(), - 'onFocus' - ) - const mutationCacheOnOnlineSpy = jest.spyOn( - testClient.getMutationCache(), - 'onOnline' + 'resumePausedMutations' ) focusManager.setFocused(false) expect(queryCacheOnFocusSpy).not.toHaveBeenCalled() - expect(mutationCacheOnFocusSpy).not.toHaveBeenCalled() + expect(mutationCacheResumePausedMutationsSpy).not.toHaveBeenCalled() focusManager.setFocused(true) expect(queryCacheOnFocusSpy).toHaveBeenCalledTimes(1) - expect(queryCacheOnFocusSpy).toHaveBeenCalledTimes(1) + expect(mutationCacheResumePausedMutationsSpy).toHaveBeenCalledTimes(1) expect(queryCacheOnOnlineSpy).not.toHaveBeenCalled() - expect(mutationCacheOnOnlineSpy).not.toHaveBeenCalled() queryCacheOnFocusSpy.mockRestore() - mutationCacheOnFocusSpy.mockRestore() + mutationCacheResumePausedMutationsSpy.mockRestore() queryCacheOnOnlineSpy.mockRestore() - mutationCacheOnOnlineSpy.mockRestore() + focusManager.setFocused(undefined) }) test('should notify queryCache and mutationCache if online', async () => { @@ -1462,30 +1457,25 @@ describe('queryClient', () => { testClient.getQueryCache(), 'onOnline' ) - const mutationCacheOnFocusSpy = jest.spyOn( - testClient.getMutationCache(), - 'onFocus' - ) - const mutationCacheOnOnlineSpy = jest.spyOn( + const mutationCacheResumePausedMutationsSpy = jest.spyOn( testClient.getMutationCache(), - 'onOnline' + 'resumePausedMutations' ) onlineManager.setOnline(false) expect(queryCacheOnOnlineSpy).not.toHaveBeenCalled() - expect(queryCacheOnOnlineSpy).not.toHaveBeenCalled() + expect(mutationCacheResumePausedMutationsSpy).not.toHaveBeenCalled() onlineManager.setOnline(true) expect(queryCacheOnOnlineSpy).toHaveBeenCalledTimes(1) - expect(queryCacheOnOnlineSpy).toHaveBeenCalledTimes(1) + expect(mutationCacheResumePausedMutationsSpy).toHaveBeenCalledTimes(1) - expect(mutationCacheOnFocusSpy).not.toHaveBeenCalled() - expect(mutationCacheOnFocusSpy).not.toHaveBeenCalled() + expect(queryCacheOnFocusSpy).not.toHaveBeenCalled() queryCacheOnFocusSpy.mockRestore() - mutationCacheOnFocusSpy.mockRestore() queryCacheOnOnlineSpy.mockRestore() - mutationCacheOnOnlineSpy.mockRestore() + mutationCacheResumePausedMutationsSpy.mockRestore() + onlineManager.setOnline(undefined) }) }) diff --git a/src/core/tests/queryObserver.test.tsx b/src/core/tests/queryObserver.test.tsx index ed95023aaf..af89f3d576 100644 --- a/src/core/tests/queryObserver.test.tsx +++ b/src/core/tests/queryObserver.test.tsx @@ -25,7 +25,7 @@ describe('queryObserver', () => { test('should trigger a fetch when subscribed', async () => { const key = queryKey() - const queryFn = jest.fn() + const queryFn = jest.fn().mockReturnValue('data') const observer = new QueryObserver(queryClient, { queryKey: key, queryFn }) const unsubscribe = observer.subscribe(() => undefined) await sleep(1) @@ -309,7 +309,7 @@ describe('queryObserver', () => { test('should not trigger a fetch when subscribed and disabled', async () => { const key = queryKey() - const queryFn = jest.fn() + const queryFn = jest.fn().mockReturnValue('data') const observer = new QueryObserver(queryClient, { queryKey: key, queryFn, @@ -323,7 +323,7 @@ describe('queryObserver', () => { test('should not trigger a fetch when not subscribed', async () => { const key = queryKey() - const queryFn = jest.fn() + const queryFn = jest.fn().mockReturnValue('data') new QueryObserver(queryClient, { queryKey: key, queryFn }) await sleep(1) expect(queryFn).toHaveBeenCalledTimes(0) @@ -394,40 +394,6 @@ describe('queryObserver', () => { expect(results2[1]).toMatchObject({ data: 'data' }) }) - test('should be able to resolve a promise', async () => { - const key = queryKey() - const queryFn = jest.fn().mockReturnValue('data') - const observer = new QueryObserver(queryClient, { - queryKey: key, - enabled: false, - }) - let value - observer.getNextResult().then(x => { - value = x - }) - queryClient.prefetchQuery(key, queryFn) - await sleep(50) - expect(queryFn).toHaveBeenCalledTimes(1) - expect(value).toMatchObject({ data: 'data' }) - }) - - test('should be able to resolve a promise with an error', async () => { - const consoleMock = mockConsoleError() - const key = queryKey() - const observer = new QueryObserver(queryClient, { - queryKey: key, - enabled: false, - }) - let error - observer.getNextResult({ throwOnError: true }).catch(e => { - error = e - }) - queryClient.prefetchQuery(key, () => Promise.reject('reject')) - await sleep(50) - expect(error).toEqual('reject') - consoleMock.mockRestore() - }) - test('should stop retry when unsubscribing', async () => { const consoleMock = mockConsoleError() const key = queryKey() @@ -578,7 +544,7 @@ describe('queryObserver', () => { test('should not refetch in background if refetchIntervalInBackground is false', async () => { const key = queryKey() - const queryFn = jest.fn() + const queryFn = jest.fn().mockReturnValue('data') focusManager.setFocused(false) const observer = new QueryObserver(queryClient, { diff --git a/src/reactjs/tests/ssr.test.tsx b/src/reactjs/tests/ssr.test.tsx index 1a2c738331..c136e42f72 100644 --- a/src/reactjs/tests/ssr.test.tsx +++ b/src/reactjs/tests/ssr.test.tsx @@ -20,7 +20,7 @@ describe('Server Side Rendering', () => { const queryCache = new QueryCache() const queryClient = new QueryClient({ queryCache }) const key = queryKey() - const queryFn = jest.fn() + const queryFn = jest.fn().mockReturnValue('data') function Page() { const query = useQuery(key, queryFn) diff --git a/src/reactjs/tests/useQuery.test.tsx b/src/reactjs/tests/useQuery.test.tsx index 6a68bd126d..c01af84af3 100644 --- a/src/reactjs/tests/useQuery.test.tsx +++ b/src/reactjs/tests/useQuery.test.tsx @@ -2416,7 +2416,7 @@ describe('useQuery', () => { it('should not refetch query on focus when `enabled` is set to `false`', async () => { const key = queryKey() - const queryFn = jest.fn() + const queryFn = jest.fn().mockReturnValue('data') function Page() { const { data = 'default' } = useQuery(key, queryFn, { @@ -3648,7 +3648,7 @@ describe('useQuery', () => { it('should not cause memo churn when data does not change', async () => { const key = queryKey() - const queryFn = jest.fn() + const queryFn = jest.fn().mockReturnValue('data') const memoFn = jest.fn() function Page() {