@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.
Files changed (54) hide show
  1. package/dist/index.d.ts +257 -200
  2. package/dist/index.js +364 -253
  3. package/dist/index.js.map +1 -1
  4. package/package.json +6 -9
  5. package/src/_exports/index.ts +2 -0
  6. package/src/_exports/sdk-react.ts +4 -0
  7. package/src/components/SDKProvider.test.tsx +5 -12
  8. package/src/components/SDKProvider.tsx +26 -24
  9. package/src/config/handles.ts +55 -0
  10. package/src/constants.ts +5 -0
  11. package/src/context/DefaultResourceContext.ts +10 -0
  12. package/src/context/PerspectiveContext.ts +12 -0
  13. package/src/context/ResourceProvider.test.tsx +2 -2
  14. package/src/context/ResourceProvider.tsx +53 -49
  15. package/src/hooks/agent/agentActions.ts +55 -38
  16. package/src/hooks/context/useResource.test.tsx +32 -0
  17. package/src/hooks/context/useResource.ts +24 -0
  18. package/src/hooks/context/useSanityInstance.test.tsx +42 -111
  19. package/src/hooks/context/useSanityInstance.ts +28 -50
  20. package/src/hooks/dashboard/useDispatchIntent.test.ts +5 -1
  21. package/src/hooks/dashboard/useDispatchIntent.ts +3 -3
  22. package/src/hooks/dashboard/useManageFavorite.test.tsx +16 -12
  23. package/src/hooks/dashboard/utils/useResourceIdFromDocumentHandle.ts +1 -5
  24. package/src/hooks/document/{useApplyDocumentActions.test.ts → useApplyDocumentActions.test.tsx} +42 -77
  25. package/src/hooks/document/useApplyDocumentActions.ts +28 -62
  26. package/src/hooks/document/useDocument.ts +3 -5
  27. package/src/hooks/document/useDocumentEvent.ts +4 -3
  28. package/src/hooks/document/useDocumentPermissions.test.tsx +58 -150
  29. package/src/hooks/document/useDocumentPermissions.ts +78 -55
  30. package/src/hooks/document/useEditDocument.test.tsx +25 -60
  31. package/src/hooks/document/useEditDocument.ts +1 -1
  32. package/src/hooks/documents/useDocuments.ts +13 -8
  33. package/src/hooks/helpers/createStateSourceHook.tsx +1 -2
  34. package/src/hooks/helpers/useNormalizedResourceOptions.test.tsx +253 -0
  35. package/src/hooks/helpers/useNormalizedResourceOptions.ts +85 -47
  36. package/src/hooks/organizations/useOrganization.test-d.ts +53 -0
  37. package/src/hooks/organizations/useOrganization.test.ts +65 -0
  38. package/src/hooks/organizations/useOrganization.ts +40 -0
  39. package/src/hooks/organizations/useOrganizations.test-d.ts +55 -0
  40. package/src/hooks/organizations/useOrganizations.test.ts +85 -0
  41. package/src/hooks/organizations/useOrganizations.ts +45 -0
  42. package/src/hooks/paginatedDocuments/usePaginatedDocuments.ts +23 -9
  43. package/src/hooks/presence/usePresence.ts +4 -11
  44. package/src/hooks/preview/useDocumentPreview.tsx +4 -7
  45. package/src/hooks/projection/useDocumentProjection.ts +5 -7
  46. package/src/hooks/projects/useProject.test-d.ts +49 -0
  47. package/src/hooks/projects/useProject.ts +33 -41
  48. package/src/hooks/projects/useProjects.test-d.ts +49 -0
  49. package/src/hooks/projects/useProjects.ts +17 -23
  50. package/src/hooks/query/useQuery.ts +1 -1
  51. package/src/hooks/releases/useActiveReleases.ts +6 -6
  52. package/src/hooks/releases/usePerspective.ts +7 -12
  53. package/src/hooks/users/useUser.ts +1 -1
  54. 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 hierarchy of instances
103
- const grandparent = createSanityInstance({projectId: 'gp', dataset: 'gp-ds'})
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 child instance and no config
44
+ // Render the hook with the wrapper that provides the context
108
45
  const {result} = renderHook(() => useSanityInstance(), {
109
- wrapper: createWrapper(child),
46
+ wrapper: createWrapper(instance),
110
47
  })
111
48
 
112
- // Should return the child instance
113
- expect(result.current).toBe(child)
49
+ // Should return the instance
50
+ expect(result.current).toBe(instance)
114
51
  })
115
52
 
116
- it('should match child instance when it satisfies the config', () => {
117
- // Create a parent instance
118
- const parent = createSanityInstance({projectId: 'parent', dataset: 'parent-ds'})
53
+ describe('deprecated config parameter', () => {
54
+ let warnSpy: ReturnType<typeof vi.spyOn>
119
55
 
120
- // Create a child instance that inherits projectId
121
- const child = parent.createChild({dataset: 'child-ds'})
56
+ beforeEach(() => {
57
+ warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {})
58
+ })
122
59
 
123
- // Render the hook with the child instance and request by the child's dataset
124
- const {result} = renderHook(() => useSanityInstance({dataset: 'child-ds'}), {
125
- wrapper: createWrapper(child),
60
+ afterEach(() => {
61
+ warnSpy.mockRestore()
126
62
  })
127
63
 
128
- // Should match and return the child instance
129
- expect(result.current).toBe(child)
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
- it('should match partial config correctly', () => {
133
- // Create an instance with multiple config values
134
- const instance = createSanityInstance({
135
- projectId: 'test-proj',
136
- dataset: 'test-ds',
68
+ const {result} = renderHook(() => useSanityInstance(requestedConfig), {
69
+ wrapper: createWrapper(instance),
70
+ })
71
+
72
+ expect(result.current).toBe(instance)
137
73
  })
138
74
 
139
- // Should match when requesting just one property
140
- const {result} = renderHook(() => useSanityInstance({dataset: 'test-ds'}), {
141
- wrapper: createWrapper(instance),
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
- expect(result.current).toBe(instance)
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
- it("should match deeper in hierarchy when current instance doesn't match", () => {
148
- // Create a three-level hierarchy
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
- // Request config matching the root from the leaf
154
- const {result} = renderHook(() => useSanityInstance({projectId: 'root', dataset: 'root-ds'}), {
155
- wrapper: createWrapper(leaf),
92
+ rerender()
93
+ rerender()
94
+ expect(warnSpy).toHaveBeenCalledTimes(1)
156
95
  })
157
96
 
158
- // Should find and return the root instance
159
- expect(result.current).toBe(root)
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
- it('should match undefined values in config', () => {
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 or finds a matching instance from the hierarchy
9
+ * Retrieves the current Sanity instance from context
8
10
  *
9
11
  * @public
10
12
  *
11
13
  * @category Platform
12
- * @param config - Optional configuration to match against when finding an instance
13
- * @returns The current or matching Sanity instance
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. When provided with
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 = (config?: SanityConfig): SanityInstance => {
61
- const instance = useContext(SanityInstanceContext)
62
-
63
- if (!instance) {
64
- throw new Error(
65
- `SanityInstance context not found. ${config ? `Requested config: ${JSON.stringify(config, null, 2)}. ` : ''}Please ensure that your component is wrapped in a ResourceProvider or a SanityApp component.`,
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
- if (!config) return instance
49
+ const instance = useContext(SanityInstanceContext)
70
50
 
71
- const match = instance.match(config)
72
- if (!match) {
51
+ if (!instance) {
73
52
  throw new Error(
74
- `Could not find a matching Sanity instance for the requested configuration: ${JSON.stringify(config, null, 2)}.
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 match
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
- const {result} = renderHook(() =>
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 DocumentHandle, type FrameMessage} from '@sanity/sdk'
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: WithResourceNameSupport<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: ReturnType<typeof vi.fn>
27
- let mockSendMessage: ReturnType<typeof vi.fn>
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
- return {
63
- fetch: (type: string, data?: unknown, options: unknown = {}) =>
64
- mockFetch(type, data, options),
65
- sendMessage: mockSendMessage,
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 {projectId, dataset, resource} = options
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}`
@@ -1,7 +1,9 @@
1
- import {applyDocumentActions, type SanityInstance} from '@sanity/sdk'
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
- // These are quite fragile mocks, but they are useful enough for now.
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 SanityInstance', async () => {
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.match when projectId is overrideen', async () => {
54
- const {result} = renderHook(() => useApplyDocumentActions())
55
- result.current({
56
- type: 'document.edit',
57
- documentType: 'post',
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('uses SanityInstance.amcth when projectId and dataset is overrideen', async () => {
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(instances['p123.d123'], {
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 project IDs found in actions/)
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 datasets found in actions/)
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: 'p',
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: 'p', dataset: 'd'},
177
+ resource: {projectId: 'p2', dataset: 'd'},
214
178
  },
215
179
  ])
216
- }).toThrow(/Mismatches between projectId\/dataset options and resource/)
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: 'p', dataset: 'd'},
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: 'p',
197
+ projectId: 'p2',
198
+ dataset: 'd',
234
199
  },
235
200
  ])
236
- }).toThrow(/Mismatches between projectId\/dataset options and resource/)
201
+ }).toThrow(/Mismatched resources found in actions/)
237
202
  })
238
203
  })