@sanity/sdk-react 2.10.0 → 2.11.0
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/dist/index.d.ts +257 -200
- package/dist/index.js +364 -253
- package/dist/index.js.map +1 -1
- package/package.json +6 -9
- package/src/_exports/index.ts +2 -0
- package/src/_exports/sdk-react.ts +4 -0
- package/src/components/SDKProvider.test.tsx +5 -12
- package/src/components/SDKProvider.tsx +26 -24
- package/src/config/handles.ts +55 -0
- package/src/constants.ts +5 -0
- package/src/context/DefaultResourceContext.ts +10 -0
- package/src/context/PerspectiveContext.ts +12 -0
- package/src/context/ResourceProvider.test.tsx +2 -2
- package/src/context/ResourceProvider.tsx +53 -49
- package/src/hooks/agent/agentActions.ts +55 -38
- package/src/hooks/context/useResource.test.tsx +32 -0
- package/src/hooks/context/useResource.ts +24 -0
- package/src/hooks/context/useSanityInstance.test.tsx +42 -111
- package/src/hooks/context/useSanityInstance.ts +28 -50
- package/src/hooks/dashboard/useDispatchIntent.test.ts +5 -1
- package/src/hooks/dashboard/useDispatchIntent.ts +3 -3
- package/src/hooks/dashboard/useManageFavorite.test.tsx +16 -12
- package/src/hooks/dashboard/utils/useResourceIdFromDocumentHandle.ts +1 -5
- package/src/hooks/document/{useApplyDocumentActions.test.ts → useApplyDocumentActions.test.tsx} +42 -77
- package/src/hooks/document/useApplyDocumentActions.ts +28 -62
- package/src/hooks/document/useDocument.ts +3 -5
- package/src/hooks/document/useDocumentEvent.ts +4 -3
- package/src/hooks/document/useDocumentPermissions.test.tsx +58 -150
- package/src/hooks/document/useDocumentPermissions.ts +78 -55
- package/src/hooks/document/useEditDocument.test.tsx +25 -60
- package/src/hooks/document/useEditDocument.ts +1 -1
- package/src/hooks/documents/useDocuments.ts +13 -8
- package/src/hooks/helpers/createStateSourceHook.tsx +1 -2
- package/src/hooks/helpers/useNormalizedResourceOptions.test.tsx +253 -0
- package/src/hooks/helpers/useNormalizedResourceOptions.ts +85 -47
- package/src/hooks/organizations/useOrganization.test-d.ts +53 -0
- package/src/hooks/organizations/useOrganization.test.ts +65 -0
- package/src/hooks/organizations/useOrganization.ts +40 -0
- package/src/hooks/organizations/useOrganizations.test-d.ts +55 -0
- package/src/hooks/organizations/useOrganizations.test.ts +85 -0
- package/src/hooks/organizations/useOrganizations.ts +45 -0
- package/src/hooks/paginatedDocuments/usePaginatedDocuments.ts +23 -9
- package/src/hooks/presence/usePresence.ts +4 -11
- package/src/hooks/preview/useDocumentPreview.tsx +4 -7
- package/src/hooks/projection/useDocumentProjection.ts +5 -7
- package/src/hooks/projects/useProject.test-d.ts +49 -0
- package/src/hooks/projects/useProject.ts +33 -41
- package/src/hooks/projects/useProjects.test-d.ts +49 -0
- package/src/hooks/projects/useProjects.ts +17 -23
- package/src/hooks/query/useQuery.ts +1 -1
- package/src/hooks/releases/useActiveReleases.ts +6 -6
- package/src/hooks/releases/usePerspective.ts +7 -12
- package/src/hooks/users/useUser.ts +1 -1
- package/src/hooks/users/useUsers.ts +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {createSanityInstance, type SanityConfig, type SanityInstance} from '@sanity/sdk'
|
|
2
2
|
import {renderHook} from '@testing-library/react'
|
|
3
3
|
import {type ReactNode} from 'react'
|
|
4
|
-
import {describe, expect, it} from 'vitest'
|
|
4
|
+
import {afterEach, beforeEach, describe, expect, it, vi} from 'vitest'
|
|
5
5
|
|
|
6
6
|
import {SanityInstanceContext} from '../../context/SanityInstanceContext'
|
|
7
7
|
import {useSanityInstance} from './useSanityInstance'
|
|
@@ -37,137 +37,68 @@ describe('useSanityInstance', () => {
|
|
|
37
37
|
}).toThrow('SanityInstance context not found')
|
|
38
38
|
})
|
|
39
39
|
|
|
40
|
-
it('should include the requested config in error message when no instance found', () => {
|
|
41
|
-
const requestedConfig = {projectId: 'test', dataset: 'test'}
|
|
42
|
-
|
|
43
|
-
// Expect the hook to throw and include the requested config in the error
|
|
44
|
-
expect(() => {
|
|
45
|
-
renderHook(() => useSanityInstance(requestedConfig), {
|
|
46
|
-
wrapper: createWrapper(null),
|
|
47
|
-
})
|
|
48
|
-
}).toThrow(JSON.stringify(requestedConfig, null, 2))
|
|
49
|
-
})
|
|
50
|
-
|
|
51
|
-
it('should find a matching instance with provided config', () => {
|
|
52
|
-
// Create a parent instance
|
|
53
|
-
const parentInstance = createSanityInstance({
|
|
54
|
-
projectId: 'parent-project',
|
|
55
|
-
dataset: 'parent-dataset',
|
|
56
|
-
})
|
|
57
|
-
|
|
58
|
-
// Create a child instance
|
|
59
|
-
const childInstance = parentInstance.createChild({dataset: 'child-dataset'})
|
|
60
|
-
|
|
61
|
-
// Render the hook with the child instance and request the parent config
|
|
62
|
-
const {result} = renderHook(
|
|
63
|
-
() => useSanityInstance({projectId: 'parent-project', dataset: 'parent-dataset'}),
|
|
64
|
-
{wrapper: createWrapper(childInstance)},
|
|
65
|
-
)
|
|
66
|
-
|
|
67
|
-
// Should match and return the parent instance
|
|
68
|
-
expect(result.current).toBe(parentInstance)
|
|
69
|
-
})
|
|
70
|
-
|
|
71
|
-
it('should throw an error if no matching instance is found for config', () => {
|
|
72
|
-
// Create an instance
|
|
73
|
-
const instance = createSanityInstance({projectId: 'test-project', dataset: 'test-dataset'})
|
|
74
|
-
|
|
75
|
-
// Request a config that doesn't match
|
|
76
|
-
const requestedConfig: SanityConfig = {
|
|
77
|
-
projectId: 'non-existent',
|
|
78
|
-
dataset: 'not-found',
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
// Expect the hook to throw for a non-matching config
|
|
82
|
-
expect(() => {
|
|
83
|
-
renderHook(() => useSanityInstance(requestedConfig), {
|
|
84
|
-
wrapper: createWrapper(instance),
|
|
85
|
-
})
|
|
86
|
-
}).toThrow('Could not find a matching Sanity instance')
|
|
87
|
-
})
|
|
88
|
-
|
|
89
|
-
it('should include the requested config in error message when no matching instance', () => {
|
|
90
|
-
const instance = createSanityInstance({projectId: 'test-project', dataset: 'test-dataset'})
|
|
91
|
-
const requestedConfig = {projectId: 'different', dataset: 'different'}
|
|
92
|
-
|
|
93
|
-
// Expect the error to include the requested config details
|
|
94
|
-
expect(() => {
|
|
95
|
-
renderHook(() => useSanityInstance(requestedConfig), {
|
|
96
|
-
wrapper: createWrapper(instance),
|
|
97
|
-
})
|
|
98
|
-
}).toThrow(JSON.stringify(requestedConfig, null, 2))
|
|
99
|
-
})
|
|
100
|
-
|
|
101
40
|
it('should return the current instance when no config is provided', () => {
|
|
102
|
-
// Create a
|
|
103
|
-
const
|
|
104
|
-
const parent = grandparent.createChild({projectId: 'p'})
|
|
105
|
-
const child = parent.createChild({dataset: 'child-ds'})
|
|
41
|
+
// Create a Sanity instance
|
|
42
|
+
const instance = createSanityInstance({projectId: 'gp', dataset: 'gp-ds'})
|
|
106
43
|
|
|
107
|
-
// Render the hook with the
|
|
44
|
+
// Render the hook with the wrapper that provides the context
|
|
108
45
|
const {result} = renderHook(() => useSanityInstance(), {
|
|
109
|
-
wrapper: createWrapper(
|
|
46
|
+
wrapper: createWrapper(instance),
|
|
110
47
|
})
|
|
111
48
|
|
|
112
|
-
// Should return the
|
|
113
|
-
expect(result.current).toBe(
|
|
49
|
+
// Should return the instance
|
|
50
|
+
expect(result.current).toBe(instance)
|
|
114
51
|
})
|
|
115
52
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
const parent = createSanityInstance({projectId: 'parent', dataset: 'parent-ds'})
|
|
53
|
+
describe('deprecated config parameter', () => {
|
|
54
|
+
let warnSpy: ReturnType<typeof vi.spyOn>
|
|
119
55
|
|
|
120
|
-
|
|
121
|
-
|
|
56
|
+
beforeEach(() => {
|
|
57
|
+
warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {})
|
|
58
|
+
})
|
|
122
59
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
wrapper: createWrapper(child),
|
|
60
|
+
afterEach(() => {
|
|
61
|
+
warnSpy.mockRestore()
|
|
126
62
|
})
|
|
127
63
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
64
|
+
it('should return the current context instance regardless of config', () => {
|
|
65
|
+
const instance = createSanityInstance({projectId: 'test-project', dataset: 'test-dataset'})
|
|
66
|
+
const requestedConfig: SanityConfig = {projectId: 'test-project', dataset: 'test-dataset'}
|
|
131
67
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
68
|
+
const {result} = renderHook(() => useSanityInstance(requestedConfig), {
|
|
69
|
+
wrapper: createWrapper(instance),
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
expect(result.current).toBe(instance)
|
|
137
73
|
})
|
|
138
74
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
75
|
+
it('should throw if no instance in context even when config is provided', () => {
|
|
76
|
+
expect(() => {
|
|
77
|
+
renderHook(() => useSanityInstance({projectId: 'test'}), {
|
|
78
|
+
wrapper: createWrapper(null),
|
|
79
|
+
})
|
|
80
|
+
}).toThrow('SanityInstance context not found')
|
|
142
81
|
})
|
|
143
82
|
|
|
144
|
-
|
|
145
|
-
|
|
83
|
+
it('warns once when a config argument is passed', () => {
|
|
84
|
+
const instance = createSanityInstance({projectId: 'test-project', dataset: 'test-dataset'})
|
|
85
|
+
const {rerender} = renderHook(() => useSanityInstance({projectId: 'test-project'}), {
|
|
86
|
+
wrapper: createWrapper(instance),
|
|
87
|
+
})
|
|
146
88
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
const root = createSanityInstance({projectId: 'root', dataset: 'root-ds'})
|
|
150
|
-
const middle = root.createChild({projectId: 'middle'})
|
|
151
|
-
const leaf = middle.createChild({dataset: 'leaf-ds'})
|
|
89
|
+
expect(warnSpy).toHaveBeenCalledTimes(1)
|
|
90
|
+
expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining('[useSanityInstance]'))
|
|
152
91
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
92
|
+
rerender()
|
|
93
|
+
rerender()
|
|
94
|
+
expect(warnSpy).toHaveBeenCalledTimes(1)
|
|
156
95
|
})
|
|
157
96
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
97
|
+
it('does not warn when no config is passed', () => {
|
|
98
|
+
const instance = createSanityInstance({projectId: 'test-project', dataset: 'test-dataset'})
|
|
99
|
+
renderHook(() => useSanityInstance(), {wrapper: createWrapper(instance)})
|
|
161
100
|
|
|
162
|
-
|
|
163
|
-
// Create instance with only projectId
|
|
164
|
-
const rootInstance = createSanityInstance({projectId: 'test'})
|
|
165
|
-
|
|
166
|
-
// Match specifically looking for undefined dataset
|
|
167
|
-
const {result} = renderHook(() => useSanityInstance({dataset: undefined}), {
|
|
168
|
-
wrapper: createWrapper(rootInstance),
|
|
101
|
+
expect(warnSpy).not.toHaveBeenCalled()
|
|
169
102
|
})
|
|
170
|
-
|
|
171
|
-
expect(result.current).toBe(rootInstance)
|
|
172
103
|
})
|
|
173
104
|
})
|
|
@@ -3,78 +3,56 @@ import {useContext} from 'react'
|
|
|
3
3
|
|
|
4
4
|
import {SanityInstanceContext} from '../../context/SanityInstanceContext'
|
|
5
5
|
|
|
6
|
+
const warnedCallers = new Set<string>()
|
|
7
|
+
|
|
6
8
|
/**
|
|
7
|
-
* Retrieves the current Sanity instance
|
|
9
|
+
* Retrieves the current Sanity instance from context
|
|
8
10
|
*
|
|
9
11
|
* @public
|
|
10
12
|
*
|
|
11
13
|
* @category Platform
|
|
12
|
-
* @param config -
|
|
13
|
-
* @returns The current
|
|
14
|
+
* @param config - Deprecated. Formerly used to match against the instance hierarchy.
|
|
15
|
+
* @returns The current Sanity instance
|
|
14
16
|
*
|
|
15
17
|
* @remarks
|
|
16
|
-
* This hook accesses the nearest Sanity instance from the React context.
|
|
17
|
-
* a configuration object, it traverses up the instance hierarchy to find the closest instance
|
|
18
|
-
* that matches the specified configuration using shallow comparison of properties.
|
|
19
|
-
*
|
|
18
|
+
* This hook accesses the nearest Sanity instance from the React context.
|
|
20
19
|
* The hook must be used within a component wrapped by a `ResourceProvider` or `SanityApp`.
|
|
21
20
|
*
|
|
22
|
-
* Use this hook when you need to:
|
|
23
|
-
* - Access the current SanityInstance from context
|
|
24
|
-
* - Find a specific instance with matching project/dataset configuration
|
|
25
|
-
* - Access a parent instance with specific configuration values
|
|
26
|
-
*
|
|
27
21
|
* @example Get the current instance
|
|
28
22
|
* ```tsx
|
|
29
|
-
* // Get the current instance from context
|
|
30
23
|
* const instance = useSanityInstance()
|
|
31
24
|
* console.log(instance.config.projectId)
|
|
32
25
|
* ```
|
|
33
26
|
*
|
|
34
|
-
* @example Find an instance with specific configuration
|
|
35
|
-
* ```tsx
|
|
36
|
-
* // Find an instance matching the given project and dataset
|
|
37
|
-
* const instance = useSanityInstance({
|
|
38
|
-
* projectId: 'abc123',
|
|
39
|
-
* dataset: 'production'
|
|
40
|
-
* })
|
|
41
|
-
*
|
|
42
|
-
* // Use instance for API calls
|
|
43
|
-
* const fetchDocument = (docId) => {
|
|
44
|
-
* // Instance is guaranteed to have the matching config
|
|
45
|
-
* return client.fetch(`*[_id == $id][0]`, { id: docId })
|
|
46
|
-
* }
|
|
47
|
-
* ```
|
|
48
|
-
*
|
|
49
|
-
* @example Match partial configuration
|
|
50
|
-
* ```tsx
|
|
51
|
-
* // Find an instance with specific auth configuration
|
|
52
|
-
* const instance = useSanityInstance({
|
|
53
|
-
* auth: { requireLogin: true }
|
|
54
|
-
* })
|
|
55
|
-
* ```
|
|
56
|
-
*
|
|
57
27
|
* @throws Error if no SanityInstance is found in context
|
|
58
|
-
* @throws Error if no matching instance is found for the provided config
|
|
59
28
|
*/
|
|
60
|
-
export const useSanityInstance = (
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
29
|
+
export const useSanityInstance = (
|
|
30
|
+
/**
|
|
31
|
+
* @deprecated Passing a config to match against the instance hierarchy is deprecated.
|
|
32
|
+
* Use `useSanityInstance()` without arguments instead.
|
|
33
|
+
*/
|
|
34
|
+
config?: SanityConfig,
|
|
35
|
+
): SanityInstance => {
|
|
36
|
+
if (config !== undefined) {
|
|
37
|
+
const caller = new Error().stack?.split('\n')[2]?.trim() ?? 'unknown'
|
|
38
|
+
if (!warnedCallers.has(caller)) {
|
|
39
|
+
warnedCallers.add(caller)
|
|
40
|
+
// eslint-disable-next-line no-console
|
|
41
|
+
console.warn(
|
|
42
|
+
'[useSanityInstance] Passing a config argument is deprecated and has no effect. ' +
|
|
43
|
+
'SDK apps use a single instance for all resources, so the config argument is no longer needed. ' +
|
|
44
|
+
'Call useSanityInstance() without arguments instead, or useResource() to get your currently active resource.',
|
|
45
|
+
)
|
|
46
|
+
}
|
|
67
47
|
}
|
|
68
48
|
|
|
69
|
-
|
|
49
|
+
const instance = useContext(SanityInstanceContext)
|
|
70
50
|
|
|
71
|
-
|
|
72
|
-
if (!match) {
|
|
51
|
+
if (!instance) {
|
|
73
52
|
throw new Error(
|
|
74
|
-
`
|
|
75
|
-
Please ensure there is a ResourceProvider component with a matching configuration in the component hierarchy.`,
|
|
53
|
+
`SanityInstance context not found. Please ensure that your component is wrapped in a ResourceProvider or a SanityApp component.`,
|
|
76
54
|
)
|
|
77
55
|
}
|
|
78
56
|
|
|
79
|
-
return
|
|
57
|
+
return instance
|
|
80
58
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {type DocumentHandle} from '@sanity/sdk'
|
|
2
|
+
import {renderHook as reactRenderHook} from '@testing-library/react'
|
|
2
3
|
import {beforeEach, describe, expect, it, vi} from 'vitest'
|
|
3
4
|
|
|
4
5
|
import {renderHook} from '../../../test/test-utils'
|
|
@@ -227,12 +228,14 @@ describe('useDispatchIntent', () => {
|
|
|
227
228
|
|
|
228
229
|
describe('error handling', () => {
|
|
229
230
|
it('should throw error when neither resource nor projectId/dataset is provided', () => {
|
|
231
|
+
const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
|
|
230
232
|
const invalidHandle = {
|
|
231
233
|
documentId: 'test-document-id',
|
|
232
234
|
documentType: 'test-document-type',
|
|
233
235
|
}
|
|
234
236
|
|
|
235
|
-
|
|
237
|
+
// Use a minimal wrapper with no resource context so the normalization has nothing to fall back to
|
|
238
|
+
const {result} = reactRenderHook(() =>
|
|
236
239
|
useDispatchIntent({
|
|
237
240
|
action: 'edit',
|
|
238
241
|
documentHandle: invalidHandle as unknown as DocumentHandle,
|
|
@@ -242,6 +245,7 @@ describe('useDispatchIntent', () => {
|
|
|
242
245
|
expect(() => result.current.dispatchIntent()).toThrow(
|
|
243
246
|
'useDispatchIntent: Unable to determine resource. Either `resource`, `resourceName`, or both `projectId` and `dataset` must be provided in documentHandle.',
|
|
244
247
|
)
|
|
248
|
+
consoleErrorSpy.mockRestore()
|
|
245
249
|
})
|
|
246
250
|
})
|
|
247
251
|
})
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {SDK_CHANNEL_NAME, SDK_NODE_NAME} from '@sanity/message-protocol'
|
|
2
|
-
import {type
|
|
2
|
+
import {type FrameMessage} from '@sanity/sdk'
|
|
3
3
|
import {useCallback} from 'react'
|
|
4
4
|
|
|
5
|
+
import {type DocumentHandle} from '../../config/handles'
|
|
5
6
|
import {useWindowConnection} from '../comlink/useWindowConnection'
|
|
6
|
-
import {type WithResourceNameSupport} from '../helpers/useNormalizedResourceOptions'
|
|
7
7
|
import {useResourceIdFromDocumentHandle} from './utils/useResourceIdFromDocumentHandle'
|
|
8
8
|
|
|
9
9
|
/**
|
|
@@ -42,7 +42,7 @@ interface DispatchIntent {
|
|
|
42
42
|
interface UseDispatchIntentParams {
|
|
43
43
|
action?: 'edit'
|
|
44
44
|
intentId?: string
|
|
45
|
-
documentHandle:
|
|
45
|
+
documentHandle: DocumentHandle
|
|
46
46
|
parameters?: Record<string, unknown>
|
|
47
47
|
}
|
|
48
48
|
|
|
@@ -2,12 +2,15 @@ import {type Message} from '@sanity/comlink'
|
|
|
2
2
|
import {type FavoriteStatusResponse, getFavoritesState, resolveFavoritesState} from '@sanity/sdk'
|
|
3
3
|
import {act, renderHook} from '@testing-library/react'
|
|
4
4
|
import {BehaviorSubject} from 'rxjs'
|
|
5
|
-
import {beforeEach, describe, expect, it, vi} from 'vitest'
|
|
5
|
+
import {beforeEach, describe, expect, it, type Mock, vi} from 'vitest'
|
|
6
6
|
|
|
7
7
|
import {ResourceProvider} from '../../context/ResourceProvider'
|
|
8
8
|
import {useWindowConnection, type WindowConnection} from '../comlink/useWindowConnection'
|
|
9
9
|
import {useManageFavorite} from './useManageFavorite'
|
|
10
10
|
|
|
11
|
+
type MockFetch = (type: string, data?: unknown, options?: unknown) => Promise<{success: boolean}>
|
|
12
|
+
type MockSendMessage = (type: string, data?: unknown) => void
|
|
13
|
+
|
|
11
14
|
vi.mock(import('@sanity/sdk'), async (importOriginal) => {
|
|
12
15
|
const actual = await importOriginal()
|
|
13
16
|
return {
|
|
@@ -23,8 +26,8 @@ vi.mock('../comlink/useWindowConnection', () => ({
|
|
|
23
26
|
|
|
24
27
|
describe('useManageFavorite', () => {
|
|
25
28
|
let favoriteStatusSubject: BehaviorSubject<FavoriteStatusResponse>
|
|
26
|
-
let mockFetch:
|
|
27
|
-
let mockSendMessage:
|
|
29
|
+
let mockFetch: Mock<MockFetch>
|
|
30
|
+
let mockSendMessage: Mock<MockSendMessage>
|
|
28
31
|
|
|
29
32
|
const mockDocumentHandle = {
|
|
30
33
|
documentId: 'mock-id',
|
|
@@ -56,15 +59,16 @@ describe('useManageFavorite', () => {
|
|
|
56
59
|
})
|
|
57
60
|
|
|
58
61
|
// Mock useWindowConnection
|
|
59
|
-
mockFetch = vi.fn().mockResolvedValue({success: true})
|
|
60
|
-
mockSendMessage = vi.fn()
|
|
61
|
-
vi.mocked(useWindowConnection).mockImplementation(
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
62
|
+
mockFetch = vi.fn<MockFetch>().mockResolvedValue({success: true})
|
|
63
|
+
mockSendMessage = vi.fn<MockSendMessage>()
|
|
64
|
+
vi.mocked(useWindowConnection).mockImplementation(
|
|
65
|
+
() =>
|
|
66
|
+
({
|
|
67
|
+
fetch: (type: string, data?: unknown, options: unknown = {}) =>
|
|
68
|
+
mockFetch(type, data, options),
|
|
69
|
+
sendMessage: mockSendMessage,
|
|
70
|
+
}) as unknown as WindowConnection<Message>,
|
|
71
|
+
)
|
|
68
72
|
})
|
|
69
73
|
|
|
70
74
|
afterEach(() => {
|
|
@@ -19,13 +19,9 @@ export function useResourceIdFromDocumentHandle(
|
|
|
19
19
|
documentHandle: DocumentHandle,
|
|
20
20
|
): DashboardMessageResource {
|
|
21
21
|
const options = useNormalizedResourceOptions(documentHandle)
|
|
22
|
-
const {
|
|
22
|
+
const {resource} = options
|
|
23
23
|
let resourceId: string = ''
|
|
24
24
|
let resourceType: 'media-library' | 'canvas' | undefined
|
|
25
|
-
if (projectId && dataset) {
|
|
26
|
-
resourceId = `${projectId}.${dataset}`
|
|
27
|
-
}
|
|
28
|
-
|
|
29
25
|
if (resource) {
|
|
30
26
|
if (isDatasetResource(resource)) {
|
|
31
27
|
resourceId = `${resource.projectId}.${resource.dataset}`
|
package/src/hooks/document/{useApplyDocumentActions.test.ts → useApplyDocumentActions.test.tsx}
RENAMED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import {applyDocumentActions,
|
|
1
|
+
import {applyDocumentActions, createSanityInstance} from '@sanity/sdk'
|
|
2
|
+
import {renderHook as reactRenderHook} from '@testing-library/react'
|
|
2
3
|
import {describe, it} from 'vitest'
|
|
3
4
|
|
|
4
5
|
import {renderHook} from '../../../test/test-utils'
|
|
6
|
+
import {SanityInstanceContext} from '../../context/SanityInstanceContext'
|
|
5
7
|
import {useSanityInstance} from '../context/useSanityInstance'
|
|
6
8
|
import {useApplyDocumentActions} from './useApplyDocumentActions'
|
|
7
9
|
|
|
@@ -12,18 +14,7 @@ vi.mock('@sanity/sdk', async (importOriginal) => {
|
|
|
12
14
|
|
|
13
15
|
vi.mock('../context/useSanityInstance')
|
|
14
16
|
|
|
15
|
-
|
|
16
|
-
const instances: Record<string, SanityInstance | undefined> = {
|
|
17
|
-
'p123.d': {__id: 'p123.d'} as unknown as SanityInstance,
|
|
18
|
-
'p.d123': {__id: 'p.d123'} as unknown as SanityInstance,
|
|
19
|
-
'p123.d123': {__id: 'p123.d123'} as unknown as SanityInstance,
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
const instance = {
|
|
23
|
-
match({projectId = 'p', dataset = 'd'}): SanityInstance | undefined {
|
|
24
|
-
return instances[`${projectId}.${dataset}`]
|
|
25
|
-
},
|
|
26
|
-
} as unknown as SanityInstance
|
|
17
|
+
const instance = createSanityInstance({projectId: 'p', dataset: 'd'})
|
|
27
18
|
|
|
28
19
|
describe('useApplyDocumentActions', () => {
|
|
29
20
|
beforeEach(() => {
|
|
@@ -31,7 +22,7 @@ describe('useApplyDocumentActions', () => {
|
|
|
31
22
|
vi.mocked(useSanityInstance).mockReturnValueOnce(instance)
|
|
32
23
|
})
|
|
33
24
|
|
|
34
|
-
it('uses the
|
|
25
|
+
it('uses the effective context resource', async () => {
|
|
35
26
|
const {result} = renderHook(() => useApplyDocumentActions())
|
|
36
27
|
result.current({
|
|
37
28
|
type: 'document.edit',
|
|
@@ -45,43 +36,28 @@ describe('useApplyDocumentActions', () => {
|
|
|
45
36
|
type: 'document.edit',
|
|
46
37
|
documentType: 'post',
|
|
47
38
|
documentId: 'abc',
|
|
39
|
+
// resource named in test-utils
|
|
40
|
+
resource: {projectId: 'test', dataset: 'test'},
|
|
48
41
|
},
|
|
49
42
|
],
|
|
43
|
+
resource: {projectId: 'test', dataset: 'test'},
|
|
50
44
|
})
|
|
51
45
|
})
|
|
52
46
|
|
|
53
|
-
it('uses SanityInstance
|
|
54
|
-
const {result} =
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
documentId: 'abc',
|
|
59
|
-
|
|
60
|
-
projectId: 'p123',
|
|
61
|
-
})
|
|
62
|
-
|
|
63
|
-
expect(applyDocumentActions).toHaveBeenCalledExactlyOnceWith(instances['p123.d'], {
|
|
64
|
-
actions: [
|
|
65
|
-
{
|
|
66
|
-
type: 'document.edit',
|
|
67
|
-
documentType: 'post',
|
|
68
|
-
documentId: 'abc',
|
|
69
|
-
|
|
70
|
-
projectId: 'p123',
|
|
71
|
-
},
|
|
72
|
-
],
|
|
73
|
-
})
|
|
74
|
-
})
|
|
75
|
-
|
|
76
|
-
it('uses SanityInstance when dataset is overrideen', async () => {
|
|
77
|
-
const {result} = renderHook(() => useApplyDocumentActions())
|
|
78
|
-
result.current({
|
|
79
|
-
type: 'document.edit',
|
|
80
|
-
documentType: 'post',
|
|
81
|
-
documentId: 'abc',
|
|
82
|
-
|
|
83
|
-
dataset: 'd123',
|
|
47
|
+
it('uses the SanityInstance when resource is not provided', async () => {
|
|
48
|
+
const {result} = reactRenderHook(() => useApplyDocumentActions(), {
|
|
49
|
+
wrapper: ({children}) => (
|
|
50
|
+
<SanityInstanceContext.Provider value={instance}>{children}</SanityInstanceContext.Provider>
|
|
51
|
+
),
|
|
84
52
|
})
|
|
53
|
+
result.current(
|
|
54
|
+
{
|
|
55
|
+
type: 'document.edit',
|
|
56
|
+
documentType: 'post',
|
|
57
|
+
documentId: 'abc',
|
|
58
|
+
},
|
|
59
|
+
{},
|
|
60
|
+
)
|
|
85
61
|
|
|
86
62
|
expect(applyDocumentActions).toHaveBeenCalledExactlyOnceWith(instance, {
|
|
87
63
|
actions: [
|
|
@@ -89,51 +65,36 @@ describe('useApplyDocumentActions', () => {
|
|
|
89
65
|
type: 'document.edit',
|
|
90
66
|
documentType: 'post',
|
|
91
67
|
documentId: 'abc',
|
|
92
|
-
|
|
93
|
-
dataset: 'd123',
|
|
68
|
+
resource: {projectId: 'p', dataset: 'd'},
|
|
94
69
|
},
|
|
95
70
|
],
|
|
71
|
+
resource: {projectId: 'p', dataset: 'd'},
|
|
96
72
|
})
|
|
97
73
|
})
|
|
98
74
|
|
|
99
|
-
it('
|
|
75
|
+
it('resolves resource from projectId and dataset in action', async () => {
|
|
100
76
|
const {result} = renderHook(() => useApplyDocumentActions())
|
|
101
77
|
result.current({
|
|
102
78
|
type: 'document.edit',
|
|
103
79
|
documentType: 'post',
|
|
104
80
|
documentId: 'abc',
|
|
105
|
-
|
|
106
|
-
projectId: 'p123',
|
|
81
|
+
projectId: 'p',
|
|
107
82
|
dataset: 'd123',
|
|
108
83
|
})
|
|
109
84
|
|
|
110
|
-
expect(applyDocumentActions).toHaveBeenCalledExactlyOnceWith(
|
|
85
|
+
expect(applyDocumentActions).toHaveBeenCalledExactlyOnceWith(instance, {
|
|
111
86
|
actions: [
|
|
112
87
|
{
|
|
113
88
|
type: 'document.edit',
|
|
114
89
|
documentType: 'post',
|
|
115
90
|
documentId: 'abc',
|
|
116
|
-
|
|
117
|
-
projectId: 'p123',
|
|
118
|
-
dataset: 'd123',
|
|
91
|
+
resource: {projectId: 'p', dataset: 'd123'},
|
|
119
92
|
},
|
|
120
93
|
],
|
|
94
|
+
resource: {projectId: 'p', dataset: 'd123'},
|
|
121
95
|
})
|
|
122
96
|
})
|
|
123
97
|
|
|
124
|
-
it("throws if SanityInstance.match doesn't find anything", async () => {
|
|
125
|
-
const {result} = renderHook(() => useApplyDocumentActions())
|
|
126
|
-
expect(() => {
|
|
127
|
-
result.current({
|
|
128
|
-
type: 'document.edit',
|
|
129
|
-
documentType: 'post',
|
|
130
|
-
documentId: 'abc',
|
|
131
|
-
|
|
132
|
-
projectId: 'other',
|
|
133
|
-
})
|
|
134
|
-
}).toThrow()
|
|
135
|
-
})
|
|
136
|
-
|
|
137
98
|
it('throws when actions have mismatched project IDs', async () => {
|
|
138
99
|
const {result} = renderHook(() => useApplyDocumentActions())
|
|
139
100
|
expect(() => {
|
|
@@ -143,15 +104,17 @@ describe('useApplyDocumentActions', () => {
|
|
|
143
104
|
documentType: 'post',
|
|
144
105
|
documentId: 'abc',
|
|
145
106
|
projectId: 'p123',
|
|
107
|
+
dataset: 'd',
|
|
146
108
|
},
|
|
147
109
|
{
|
|
148
110
|
type: 'document.edit',
|
|
149
111
|
documentType: 'post',
|
|
150
112
|
documentId: 'def',
|
|
151
113
|
projectId: 'p456',
|
|
114
|
+
dataset: 'd',
|
|
152
115
|
},
|
|
153
116
|
])
|
|
154
|
-
}).toThrow(/Mismatched
|
|
117
|
+
}).toThrow(/Mismatched resources found in actions/)
|
|
155
118
|
})
|
|
156
119
|
|
|
157
120
|
it('throws when actions have mismatched datasets', async () => {
|
|
@@ -173,7 +136,7 @@ describe('useApplyDocumentActions', () => {
|
|
|
173
136
|
dataset: 'd2',
|
|
174
137
|
},
|
|
175
138
|
])
|
|
176
|
-
}).toThrow(/Mismatched
|
|
139
|
+
}).toThrow(/Mismatched resources found in actions/)
|
|
177
140
|
})
|
|
178
141
|
|
|
179
142
|
it('throws when actions have mismatched resources', async () => {
|
|
@@ -196,7 +159,7 @@ describe('useApplyDocumentActions', () => {
|
|
|
196
159
|
}).toThrow(/Mismatched resources found in actions/)
|
|
197
160
|
})
|
|
198
161
|
|
|
199
|
-
it('throws when mixing projectId and resource (projectId first)', async () => {
|
|
162
|
+
it('throws when mixing projectId/dataset and resource with a mismatch (projectId first)', async () => {
|
|
200
163
|
const {result} = renderHook(() => useApplyDocumentActions())
|
|
201
164
|
expect(() => {
|
|
202
165
|
result.current([
|
|
@@ -204,19 +167,20 @@ describe('useApplyDocumentActions', () => {
|
|
|
204
167
|
type: 'document.edit',
|
|
205
168
|
documentType: 'post',
|
|
206
169
|
documentId: 'abc',
|
|
207
|
-
projectId: '
|
|
170
|
+
projectId: 'p1',
|
|
171
|
+
dataset: 'd',
|
|
208
172
|
},
|
|
209
173
|
{
|
|
210
174
|
type: 'document.edit',
|
|
211
175
|
documentType: 'post',
|
|
212
176
|
documentId: 'def',
|
|
213
|
-
resource: {projectId: '
|
|
177
|
+
resource: {projectId: 'p2', dataset: 'd'},
|
|
214
178
|
},
|
|
215
179
|
])
|
|
216
|
-
}).toThrow(/
|
|
180
|
+
}).toThrow(/Mismatched resources found in actions/)
|
|
217
181
|
})
|
|
218
182
|
|
|
219
|
-
it('throws when mixing resource and projectId (resource first)', async () => {
|
|
183
|
+
it('throws when mixing resource and projectId/dataset with a mismatch (resource first)', async () => {
|
|
220
184
|
const {result} = renderHook(() => useApplyDocumentActions())
|
|
221
185
|
expect(() => {
|
|
222
186
|
result.current([
|
|
@@ -224,15 +188,16 @@ describe('useApplyDocumentActions', () => {
|
|
|
224
188
|
type: 'document.edit',
|
|
225
189
|
documentType: 'post',
|
|
226
190
|
documentId: 'abc',
|
|
227
|
-
resource: {projectId: '
|
|
191
|
+
resource: {projectId: 'p1', dataset: 'd'},
|
|
228
192
|
},
|
|
229
193
|
{
|
|
230
194
|
type: 'document.edit',
|
|
231
195
|
documentType: 'post',
|
|
232
196
|
documentId: 'def',
|
|
233
|
-
projectId: '
|
|
197
|
+
projectId: 'p2',
|
|
198
|
+
dataset: 'd',
|
|
234
199
|
},
|
|
235
200
|
])
|
|
236
|
-
}).toThrow(/
|
|
201
|
+
}).toThrow(/Mismatched resources found in actions/)
|
|
237
202
|
})
|
|
238
203
|
})
|