@sanity/sdk-react 0.0.0-rc.6 → 0.0.0-rc.8
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.
- package/README.md +5 -57
- package/dist/index.d.ts +998 -437
- package/dist/index.js +324 -258
- package/dist/index.js.map +1 -1
- package/package.json +16 -15
- package/src/_exports/sdk-react.ts +4 -1
- package/src/components/SDKProvider.tsx +6 -1
- package/src/components/SanityApp.test.tsx +29 -47
- package/src/components/SanityApp.tsx +12 -11
- package/src/components/auth/AuthBoundary.test.tsx +177 -7
- package/src/components/auth/AuthBoundary.tsx +31 -1
- package/src/components/auth/ConfigurationError.ts +22 -0
- package/src/components/auth/LoginError.tsx +9 -3
- package/src/hooks/auth/useVerifyOrgProjects.test.tsx +136 -0
- package/src/hooks/auth/useVerifyOrgProjects.tsx +48 -0
- package/src/hooks/client/useClient.ts +3 -3
- package/src/hooks/comlink/useManageFavorite.test.ts +276 -27
- package/src/hooks/comlink/useManageFavorite.ts +102 -51
- package/src/hooks/comlink/useWindowConnection.ts +3 -2
- package/src/hooks/document/useApplyDocumentActions.ts +105 -31
- package/src/hooks/document/useDocument.test.ts +41 -4
- package/src/hooks/document/useDocument.ts +198 -114
- package/src/hooks/document/useDocumentEvent.test.ts +5 -5
- package/src/hooks/document/useDocumentEvent.ts +67 -23
- package/src/hooks/document/useDocumentPermissions.ts +47 -8
- package/src/hooks/document/useDocumentSyncStatus.test.ts +12 -5
- package/src/hooks/document/useDocumentSyncStatus.ts +41 -14
- package/src/hooks/document/useEditDocument.test.ts +24 -6
- package/src/hooks/document/useEditDocument.ts +238 -133
- package/src/hooks/documents/useDocuments.test.tsx +1 -1
- package/src/hooks/documents/useDocuments.ts +153 -44
- package/src/hooks/paginatedDocuments/usePaginatedDocuments.test.tsx +1 -1
- package/src/hooks/paginatedDocuments/usePaginatedDocuments.ts +120 -47
- package/src/hooks/projection/useProjection.ts +134 -46
- package/src/hooks/query/useQuery.test.tsx +4 -4
- package/src/hooks/query/useQuery.ts +115 -43
- package/src/hooks/releases/useActiveReleases.test.tsx +84 -0
- package/src/hooks/releases/useActiveReleases.ts +39 -0
- package/src/hooks/releases/usePerspective.test.tsx +120 -0
- package/src/hooks/releases/usePerspective.ts +49 -0
|
@@ -7,17 +7,21 @@ import {
|
|
|
7
7
|
SDK_NODE_NAME,
|
|
8
8
|
type StudioResource,
|
|
9
9
|
} from '@sanity/message-protocol'
|
|
10
|
-
import {
|
|
11
|
-
|
|
10
|
+
import {
|
|
11
|
+
type DocumentHandle,
|
|
12
|
+
type FavoriteStatusResponse,
|
|
13
|
+
type FrameMessage,
|
|
14
|
+
getFavoritesState,
|
|
15
|
+
resolveFavoritesState,
|
|
16
|
+
} from '@sanity/sdk'
|
|
17
|
+
import {useCallback, useMemo, useState, useSyncExternalStore} from 'react'
|
|
12
18
|
|
|
13
19
|
import {useSanityInstance} from '../context/useSanityInstance'
|
|
14
20
|
import {useWindowConnection} from './useWindowConnection'
|
|
15
21
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
favorite: () => void
|
|
20
|
-
unfavorite: () => void
|
|
22
|
+
interface ManageFavorite extends FavoriteStatusResponse {
|
|
23
|
+
favorite: () => Promise<void>
|
|
24
|
+
unfavorite: () => Promise<void>
|
|
21
25
|
isFavorited: boolean
|
|
22
26
|
isConnected: boolean
|
|
23
27
|
}
|
|
@@ -46,7 +50,7 @@ interface UseManageFavoriteProps extends DocumentHandle {
|
|
|
46
50
|
*
|
|
47
51
|
* @example
|
|
48
52
|
* ```tsx
|
|
49
|
-
* function
|
|
53
|
+
* function FavoriteButton(props: DocumentActionProps) {
|
|
50
54
|
* const {documentId, documentType} = props
|
|
51
55
|
* const {favorite, unfavorite, isFavorited, isConnected} = useManageFavorite({
|
|
52
56
|
* documentId,
|
|
@@ -61,6 +65,22 @@ interface UseManageFavoriteProps extends DocumentHandle {
|
|
|
61
65
|
* />
|
|
62
66
|
* )
|
|
63
67
|
* }
|
|
68
|
+
*
|
|
69
|
+
* // Wrap the component with Suspense since the hook may suspend
|
|
70
|
+
* function MyDocumentAction(props: DocumentActionProps) {
|
|
71
|
+
* return (
|
|
72
|
+
* <Suspense
|
|
73
|
+
* fallback={
|
|
74
|
+
* <Button
|
|
75
|
+
* text="Loading..."
|
|
76
|
+
* disabled
|
|
77
|
+
* />
|
|
78
|
+
* }
|
|
79
|
+
* >
|
|
80
|
+
* <FavoriteButton {...props} />
|
|
81
|
+
* </Suspense>
|
|
82
|
+
* )
|
|
83
|
+
* }
|
|
64
84
|
* ```
|
|
65
85
|
*/
|
|
66
86
|
export function useManageFavorite({
|
|
@@ -72,10 +92,8 @@ export function useManageFavorite({
|
|
|
72
92
|
resourceType,
|
|
73
93
|
schemaName,
|
|
74
94
|
}: UseManageFavoriteProps): ManageFavorite {
|
|
75
|
-
const [isFavorited, setIsFavorited] = useState(false) // should load this from a comlink fetch
|
|
76
95
|
const [status, setStatus] = useState<Status>('idle')
|
|
77
|
-
const
|
|
78
|
-
const {sendMessage} = useWindowConnection<Events.FavoriteMessage, FrameMessage>({
|
|
96
|
+
const {fetch} = useWindowConnection<Events.FavoriteMessage, FrameMessage>({
|
|
79
97
|
name: SDK_NODE_NAME,
|
|
80
98
|
connectTo: SDK_CHANNEL_NAME,
|
|
81
99
|
onStatus: setStatus,
|
|
@@ -90,65 +108,98 @@ export function useManageFavorite({
|
|
|
90
108
|
if (resourceType === 'studio' && (!projectId || !dataset)) {
|
|
91
109
|
throw new Error('projectId and dataset are required for studio resources')
|
|
92
110
|
}
|
|
111
|
+
// Compute the final resourceId
|
|
112
|
+
const resourceId =
|
|
113
|
+
resourceType === 'studio' && !paramResourceId ? `${projectId}.${dataset}` : paramResourceId
|
|
93
114
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
115
|
+
if (!resourceId) {
|
|
116
|
+
throw new Error('resourceId is required for media-library and canvas resources')
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// used for favoriteStore functions like getFavoritesState and resolveFavoritesState
|
|
120
|
+
const context = useMemo(
|
|
121
|
+
() => ({
|
|
122
|
+
documentId,
|
|
123
|
+
documentType,
|
|
124
|
+
resourceId,
|
|
125
|
+
resourceType,
|
|
126
|
+
schemaName,
|
|
127
|
+
}),
|
|
128
|
+
[documentId, documentType, resourceId, resourceType, schemaName],
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
// Get favorite status using StateSource
|
|
132
|
+
const favoriteState = getFavoritesState(instance, context)
|
|
133
|
+
const state = useSyncExternalStore(favoriteState.subscribe, favoriteState.getCurrent)
|
|
134
|
+
|
|
135
|
+
const isFavorited = state?.isFavorited ?? false
|
|
106
136
|
|
|
107
137
|
const handleFavoriteAction = useCallback(
|
|
108
|
-
(action: 'added' | 'removed'
|
|
109
|
-
if (!documentId || !documentType || !resourceType) return
|
|
138
|
+
async (action: 'added' | 'removed') => {
|
|
139
|
+
if (status !== 'connected' || !fetch || !documentId || !documentType || !resourceType) return
|
|
110
140
|
|
|
111
141
|
try {
|
|
112
|
-
const
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
resource: {
|
|
142
|
+
const payload = {
|
|
143
|
+
eventType: action,
|
|
144
|
+
document: {
|
|
145
|
+
id: documentId,
|
|
146
|
+
type: documentType,
|
|
147
|
+
resource: {
|
|
148
|
+
...{
|
|
120
149
|
id: resourceId,
|
|
121
150
|
type: resourceType,
|
|
122
|
-
schemaName,
|
|
123
151
|
},
|
|
152
|
+
...(schemaName ? {schemaName} : {}),
|
|
124
153
|
},
|
|
125
154
|
},
|
|
126
|
-
response: {
|
|
127
|
-
success: true,
|
|
128
|
-
},
|
|
129
155
|
}
|
|
130
156
|
|
|
131
|
-
|
|
132
|
-
|
|
157
|
+
const res = await fetch<{success: boolean}>('dashboard/v1/events/favorite/mutate', payload)
|
|
158
|
+
if (res.success) {
|
|
159
|
+
// Force a re-fetch of the favorite status after successful mutation
|
|
160
|
+
await resolveFavoritesState(instance, context)
|
|
161
|
+
}
|
|
133
162
|
} catch (err) {
|
|
134
|
-
const error = err instanceof Error ? err : new Error('Failed to update favorite status')
|
|
135
163
|
// eslint-disable-next-line no-console
|
|
136
|
-
console.error(
|
|
137
|
-
|
|
138
|
-
error,
|
|
139
|
-
)
|
|
140
|
-
throw error
|
|
164
|
+
console.error(`Failed to ${action === 'added' ? 'favorite' : 'unfavorite'} document:`, err)
|
|
165
|
+
throw err
|
|
141
166
|
}
|
|
142
167
|
},
|
|
143
|
-
[
|
|
168
|
+
[
|
|
169
|
+
fetch,
|
|
170
|
+
documentId,
|
|
171
|
+
documentType,
|
|
172
|
+
resourceId,
|
|
173
|
+
resourceType,
|
|
174
|
+
schemaName,
|
|
175
|
+
instance,
|
|
176
|
+
context,
|
|
177
|
+
status,
|
|
178
|
+
],
|
|
144
179
|
)
|
|
145
180
|
|
|
146
|
-
const favorite = useCallback(() => handleFavoriteAction('added'
|
|
181
|
+
const favorite = useCallback(() => handleFavoriteAction('added'), [handleFavoriteAction])
|
|
182
|
+
const unfavorite = useCallback(() => handleFavoriteAction('removed'), [handleFavoriteAction])
|
|
147
183
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
184
|
+
// if state is undefined, we should suspend
|
|
185
|
+
if (!state) {
|
|
186
|
+
try {
|
|
187
|
+
const promise = resolveFavoritesState(instance, context)
|
|
188
|
+
throw promise
|
|
189
|
+
} catch (err) {
|
|
190
|
+
// If we get a timeout error, return a fallback state instead of suspending
|
|
191
|
+
if (err instanceof Error && err.message === 'Favorites service connection timeout') {
|
|
192
|
+
return {
|
|
193
|
+
favorite: async () => {},
|
|
194
|
+
unfavorite: async () => {},
|
|
195
|
+
isFavorited: false,
|
|
196
|
+
isConnected: false,
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
// For other errors, continue with suspension
|
|
200
|
+
throw err
|
|
201
|
+
}
|
|
202
|
+
}
|
|
152
203
|
|
|
153
204
|
return {
|
|
154
205
|
favorite,
|
|
@@ -63,8 +63,6 @@ export function useWindowConnection<
|
|
|
63
63
|
const instance = useSanityInstance()
|
|
64
64
|
|
|
65
65
|
useEffect(() => {
|
|
66
|
-
// the type cast is unfortunate, but the generic type of the node is not known here.
|
|
67
|
-
// We know that the node is a WindowMessage node, but not the generic types.
|
|
68
66
|
const node = getOrCreateNode(instance, {
|
|
69
67
|
name,
|
|
70
68
|
connectTo,
|
|
@@ -111,6 +109,9 @@ export function useWindowConnection<
|
|
|
111
109
|
suppressWarnings?: boolean
|
|
112
110
|
},
|
|
113
111
|
): Promise<TResponse> => {
|
|
112
|
+
if (!nodeRef.current) {
|
|
113
|
+
throw new Error('Cannot fetch before connection is established')
|
|
114
|
+
}
|
|
114
115
|
return nodeRef.current?.fetch(type, data, fetchOptions ?? {}) as Promise<TResponse>
|
|
115
116
|
},
|
|
116
117
|
[],
|
|
@@ -1,50 +1,124 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
type ActionsResult,
|
|
3
|
+
applyDocumentActions,
|
|
4
|
+
type ApplyDocumentActionsOptions,
|
|
5
|
+
type DocumentAction,
|
|
6
|
+
} from '@sanity/sdk'
|
|
7
|
+
import {type SanityDocumentResult} from 'groq'
|
|
2
8
|
|
|
3
9
|
import {createCallbackHook} from '../helpers/createCallbackHook'
|
|
10
|
+
// this import is used in an `{@link useEditDocument}`
|
|
11
|
+
// eslint-disable-next-line unused-imports/no-unused-imports, import/consistent-type-specifier-style
|
|
12
|
+
import type {useEditDocument} from './useEditDocument'
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @beta
|
|
16
|
+
*/
|
|
17
|
+
interface UseApplyDocumentActions {
|
|
18
|
+
(): <
|
|
19
|
+
TDocumentType extends string = string,
|
|
20
|
+
TDataset extends string = string,
|
|
21
|
+
TProjectId extends string = string,
|
|
22
|
+
>(
|
|
23
|
+
action:
|
|
24
|
+
| DocumentAction<TDocumentType, TDataset, TProjectId>
|
|
25
|
+
| DocumentAction<TDocumentType, TDataset, TProjectId>[],
|
|
26
|
+
options?: ApplyDocumentActionsOptions,
|
|
27
|
+
) => Promise<ActionsResult<SanityDocumentResult<TDocumentType, TDataset, TProjectId>>>
|
|
28
|
+
}
|
|
4
29
|
|
|
5
30
|
/**
|
|
6
|
-
*
|
|
7
31
|
* @beta
|
|
8
32
|
*
|
|
9
|
-
* Provides a callback for applying one or more actions
|
|
33
|
+
* Provides a stable callback function for applying one or more document actions.
|
|
34
|
+
*
|
|
35
|
+
* This hook wraps the core `applyDocumentActions` functionality from `@sanity/sdk`,
|
|
36
|
+
* integrating it with the React component lifecycle and {@link SanityInstance}.
|
|
37
|
+
* It allows you to apply actions generated by functions like `createDocument`,
|
|
38
|
+
* `editDocument`, `deleteDocument`, `publishDocument`, `unpublishDocument`,
|
|
39
|
+
* and `discardDocument` to documents.
|
|
40
|
+
*
|
|
41
|
+
* Features:
|
|
42
|
+
* - Applies one or multiple `DocumentAction` objects.
|
|
43
|
+
* - Supports optimistic updates: Local state reflects changes immediately.
|
|
44
|
+
* - Handles batching: Multiple actions passed together are sent as a single atomic transaction.
|
|
45
|
+
* - Integrates with the collaborative editing engine for conflict resolution and state synchronization.
|
|
10
46
|
*
|
|
11
47
|
* @category Documents
|
|
12
|
-
* @
|
|
13
|
-
*
|
|
48
|
+
* @returns A stable callback function. When called with a single `DocumentAction` or an array of `DocumentAction`s,
|
|
49
|
+
* it returns a promise that resolves to an {@link ActionsResult}. The `ActionsResult` contains information about the
|
|
50
|
+
* outcome, including optimistic results if applicable.
|
|
51
|
+
*
|
|
52
|
+
* @remarks
|
|
53
|
+
* This hook is a fundamental part of interacting with document state programmatically.
|
|
54
|
+
* It operates within the same unified pipeline as other document hooks like `useDocument` (for reading state)
|
|
55
|
+
* and {@link useEditDocument} (a higher-level hook specifically for edits).
|
|
56
|
+
*
|
|
57
|
+
* When multiple actions are provided in a single call, they are guaranteed to be submitted
|
|
58
|
+
* as a single transaction to Content Lake. This ensures atomicity for related operations (e.g., creating and publishing a document).
|
|
59
|
+
*
|
|
60
|
+
* @function
|
|
61
|
+
*
|
|
14
62
|
* @example Publish or unpublish a document
|
|
15
|
-
* ```
|
|
16
|
-
* import {
|
|
17
|
-
*
|
|
63
|
+
* ```tsx
|
|
64
|
+
* import {
|
|
65
|
+
* publishDocument,
|
|
66
|
+
* unpublishDocument,
|
|
67
|
+
* useApplyDocumentActions,
|
|
68
|
+
* type DocumentHandle
|
|
69
|
+
* } from '@sanity/sdk-react'
|
|
70
|
+
*
|
|
71
|
+
* // Define props using the DocumentHandle type
|
|
72
|
+
* interface PublishControlsProps {
|
|
73
|
+
* doc: DocumentHandle
|
|
74
|
+
* }
|
|
75
|
+
*
|
|
76
|
+
* function PublishControls({doc}: PublishControlsProps) {
|
|
77
|
+
* const apply = useApplyDocumentActions()
|
|
18
78
|
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
79
|
+
* const handlePublish = () => apply(publishDocument(doc))
|
|
80
|
+
* const handleUnpublish = () => apply(unpublishDocument(doc))
|
|
21
81
|
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
82
|
+
* return (
|
|
83
|
+
* <>
|
|
84
|
+
* <button onClick={handlePublish}>Publish</button>
|
|
85
|
+
* <button onClick={handleUnpublish}>Unpublish</button>
|
|
86
|
+
* </>
|
|
87
|
+
* )
|
|
88
|
+
* }
|
|
26
89
|
* ```
|
|
27
90
|
*
|
|
28
91
|
* @example Create and publish a new document
|
|
29
|
-
* ```
|
|
30
|
-
* import {
|
|
31
|
-
*
|
|
92
|
+
* ```tsx
|
|
93
|
+
* import {
|
|
94
|
+
* createDocument,
|
|
95
|
+
* publishDocument,
|
|
96
|
+
* createDocumentHandle,
|
|
97
|
+
* useApplyDocumentActions
|
|
98
|
+
* } from '@sanity/sdk-react'
|
|
32
99
|
*
|
|
33
|
-
*
|
|
100
|
+
* function CreateAndPublishButton({documentType}: {documentType: string}) {
|
|
101
|
+
* const apply = useApplyDocumentActions()
|
|
34
102
|
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
* createDocument(handle),
|
|
39
|
-
* publishDocument(handle),
|
|
40
|
-
* ])
|
|
41
|
-
* }
|
|
103
|
+
* const handleCreateAndPublish = () => {
|
|
104
|
+
* // Create a new handle inside the handler
|
|
105
|
+
* const newDocHandle = createDocumentHandle({ documentId: crypto.randomUUID(), documentType })
|
|
42
106
|
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
107
|
+
* // Apply multiple actions for the new handle as a single transaction
|
|
108
|
+
* apply([
|
|
109
|
+
* createDocument(newDocHandle),
|
|
110
|
+
* publishDocument(newDocHandle),
|
|
111
|
+
* ])
|
|
112
|
+
* }
|
|
113
|
+
*
|
|
114
|
+
* return (
|
|
115
|
+
* <button onClick={handleCreateAndPublish}>
|
|
116
|
+
* I'm feeling lucky
|
|
117
|
+
* </button>
|
|
118
|
+
* )
|
|
119
|
+
* }
|
|
48
120
|
* ```
|
|
49
121
|
*/
|
|
50
|
-
export const useApplyDocumentActions = createCallbackHook(
|
|
122
|
+
export const useApplyDocumentActions = createCallbackHook(
|
|
123
|
+
applyDocumentActions,
|
|
124
|
+
) as UseApplyDocumentActions
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
} from '@sanity/sdk'
|
|
8
8
|
import {type SanityDocument} from '@sanity/types'
|
|
9
9
|
import {renderHook} from '@testing-library/react'
|
|
10
|
+
import {type DatasetScoped} from 'groq'
|
|
10
11
|
import {beforeEach, describe, expect, it, vi} from 'vitest'
|
|
11
12
|
|
|
12
13
|
import {useSanityInstance} from '../context/useSanityInstance'
|
|
@@ -21,9 +22,45 @@ vi.mock('../context/useSanityInstance', () => ({
|
|
|
21
22
|
useSanityInstance: vi.fn(),
|
|
22
23
|
}))
|
|
23
24
|
|
|
25
|
+
// Define a single generic TestDocument type
|
|
26
|
+
type UseDocumentTestType = DatasetScoped<
|
|
27
|
+
SanityDocument & {
|
|
28
|
+
_type: 'use-document-test-type'
|
|
29
|
+
foo?: string
|
|
30
|
+
extra?: boolean
|
|
31
|
+
title?: string
|
|
32
|
+
nested?: {
|
|
33
|
+
value?: number
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
'use-document-test-dataset',
|
|
37
|
+
'p'
|
|
38
|
+
>
|
|
39
|
+
|
|
40
|
+
type UseDocumentTestTypeAlt = DatasetScoped<
|
|
41
|
+
SanityDocument & {
|
|
42
|
+
_type: 'use-document-test-type'
|
|
43
|
+
bar: string[]
|
|
44
|
+
nested?: {
|
|
45
|
+
value?: number
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
'use-document-test-alt-dataset',
|
|
49
|
+
'p'
|
|
50
|
+
>
|
|
51
|
+
|
|
52
|
+
// Scope the TestDocument type to the project/datasets used in tests
|
|
53
|
+
|
|
54
|
+
declare module 'groq' {
|
|
55
|
+
interface SanitySchemas {
|
|
56
|
+
'p:use-document-test-dataset': UseDocumentTestType
|
|
57
|
+
'p:use-document-test-alt-dataset': UseDocumentTestTypeAlt
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
24
61
|
// Create a fake instance to be returned by useSanityInstance.
|
|
25
62
|
const instance = createSanityInstance({projectId: 'p', dataset: 'd'})
|
|
26
|
-
const
|
|
63
|
+
const book: SanityDocument = {
|
|
27
64
|
_id: 'doc1',
|
|
28
65
|
foo: 'bar',
|
|
29
66
|
_type: 'book',
|
|
@@ -39,7 +76,7 @@ describe('useDocument hook', () => {
|
|
|
39
76
|
})
|
|
40
77
|
|
|
41
78
|
it('returns the current document when ready (without a path)', () => {
|
|
42
|
-
const getCurrent = vi.fn().mockReturnValue(
|
|
79
|
+
const getCurrent = vi.fn().mockReturnValue(book)
|
|
43
80
|
const subscribe = vi.fn().mockReturnValue(vi.fn())
|
|
44
81
|
vi.mocked(getDocumentState).mockReturnValue({
|
|
45
82
|
getCurrent,
|
|
@@ -48,7 +85,7 @@ describe('useDocument hook', () => {
|
|
|
48
85
|
|
|
49
86
|
const {result} = renderHook(() => useDocument({documentId: 'doc1', documentType: 'book'}))
|
|
50
87
|
|
|
51
|
-
expect(result.current).toEqual(
|
|
88
|
+
expect(result.current).toEqual(book)
|
|
52
89
|
expect(getCurrent).toHaveBeenCalled()
|
|
53
90
|
expect(subscribe).toHaveBeenCalled()
|
|
54
91
|
})
|
|
@@ -61,7 +98,7 @@ describe('useDocument hook', () => {
|
|
|
61
98
|
subscribe,
|
|
62
99
|
} as unknown as StateSource<unknown>)
|
|
63
100
|
|
|
64
|
-
const resolveDocPromise = Promise.resolve(
|
|
101
|
+
const resolveDocPromise = Promise.resolve(book)
|
|
65
102
|
|
|
66
103
|
// Also, simulate resolveDocument to return a known promise.
|
|
67
104
|
vi.mocked(resolveDocument).mockReturnValue(resolveDocPromise)
|