@sanity/cli-test 0.0.2-alpha.1 → 0.0.2-alpha.11

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 (98) hide show
  1. package/README.md +228 -0
  2. package/dist/index.d.ts +516 -3
  3. package/dist/index.js +8 -0
  4. package/dist/index.js.map +1 -1
  5. package/dist/test/constants.js +21 -0
  6. package/dist/test/constants.js.map +1 -0
  7. package/dist/test/createTestClient.js +53 -0
  8. package/dist/test/createTestClient.js.map +1 -0
  9. package/dist/test/createTestToken.js +13 -0
  10. package/dist/test/createTestToken.js.map +1 -0
  11. package/dist/test/mockApi.js +5 -3
  12. package/dist/test/mockApi.js.map +1 -1
  13. package/dist/test/mockSanityCommand.js +68 -0
  14. package/dist/test/mockSanityCommand.js.map +1 -0
  15. package/dist/test/mockTelemetry.js +22 -0
  16. package/dist/test/mockTelemetry.js.map +1 -0
  17. package/dist/test/setupFixtures.js +138 -0
  18. package/dist/test/setupFixtures.js.map +1 -0
  19. package/dist/test/snapshotSerializer.js +12 -0
  20. package/dist/test/snapshotSerializer.js.map +1 -0
  21. package/dist/test/testCommand.js +11 -4
  22. package/dist/test/testCommand.js.map +1 -1
  23. package/dist/test/testFixture.js +112 -0
  24. package/dist/test/testFixture.js.map +1 -0
  25. package/dist/test/testHook.js +23 -7
  26. package/dist/test/testHook.js.map +1 -1
  27. package/dist/utils/fileExists.js +13 -0
  28. package/dist/utils/fileExists.js.map +1 -0
  29. package/dist/utils/paths.js +66 -0
  30. package/dist/utils/paths.js.map +1 -0
  31. package/dist/vitest.d.ts +116 -0
  32. package/dist/vitest.js +22 -0
  33. package/dist/vitest.js.map +1 -0
  34. package/dist/vitestWorker.js +135 -0
  35. package/dist/vitestWorker.js.map +1 -0
  36. package/fixtures/basic-app/package.json +26 -0
  37. package/fixtures/basic-app/sanity.cli.ts +12 -0
  38. package/fixtures/basic-app/src/App.css +20 -0
  39. package/fixtures/basic-app/src/App.tsx +26 -0
  40. package/fixtures/basic-app/src/ExampleComponent.css +84 -0
  41. package/fixtures/basic-app/src/ExampleComponent.tsx +38 -0
  42. package/fixtures/basic-app/tsconfig.json +17 -0
  43. package/fixtures/basic-studio/package.json +28 -0
  44. package/fixtures/basic-studio/sanity.cli.ts +11 -0
  45. package/fixtures/basic-studio/sanity.config.ts +18 -0
  46. package/fixtures/basic-studio/schemaTypes/author.ts +52 -0
  47. package/fixtures/basic-studio/schemaTypes/blockContent.ts +71 -0
  48. package/fixtures/basic-studio/schemaTypes/category.ts +20 -0
  49. package/fixtures/basic-studio/schemaTypes/index.ts +6 -0
  50. package/fixtures/basic-studio/schemaTypes/post.ts +67 -0
  51. package/fixtures/basic-studio/tsconfig.json +17 -0
  52. package/fixtures/multi-workspace-studio/package.json +28 -0
  53. package/fixtures/multi-workspace-studio/sanity.cli.ts +11 -0
  54. package/fixtures/multi-workspace-studio/sanity.config.ts +37 -0
  55. package/fixtures/multi-workspace-studio/schemaTypes/author.ts +52 -0
  56. package/fixtures/multi-workspace-studio/schemaTypes/blockContent.ts +70 -0
  57. package/fixtures/multi-workspace-studio/schemaTypes/category.ts +20 -0
  58. package/fixtures/multi-workspace-studio/schemaTypes/index.ts +6 -0
  59. package/fixtures/multi-workspace-studio/schemaTypes/post.ts +67 -0
  60. package/fixtures/multi-workspace-studio/tsconfig.json +17 -0
  61. package/fixtures/prebuilt-app/README.md +3 -0
  62. package/fixtures/prebuilt-app/dist/favicon.ico +0 -0
  63. package/fixtures/prebuilt-app/dist/index.html +102 -0
  64. package/fixtures/prebuilt-app/dist/static/sanity-CtOxKsdo.css +24 -0
  65. package/fixtures/prebuilt-app/dist/static/sanity-D4a4eOYZ.js +17 -0
  66. package/fixtures/prebuilt-app/package.json +26 -0
  67. package/fixtures/prebuilt-app/sanity.cli.ts +12 -0
  68. package/fixtures/prebuilt-app/src/App.css +20 -0
  69. package/fixtures/prebuilt-app/src/App.tsx +24 -0
  70. package/fixtures/prebuilt-app/tsconfig.json +17 -0
  71. package/fixtures/prebuilt-studio/README.md +3 -0
  72. package/fixtures/prebuilt-studio/dist/favicon.ico +0 -0
  73. package/fixtures/prebuilt-studio/dist/index.html +113 -0
  74. package/fixtures/prebuilt-studio/dist/static/sanity-DxH-rpFr.js +9 -0
  75. package/fixtures/prebuilt-studio/package.json +25 -0
  76. package/fixtures/prebuilt-studio/sanity.cli.ts +11 -0
  77. package/fixtures/prebuilt-studio/sanity.config.ts +11 -0
  78. package/fixtures/prebuilt-studio/tsconfig.json +17 -0
  79. package/fixtures/worst-case-studio/README.md +21 -0
  80. package/fixtures/worst-case-studio/package.json +32 -0
  81. package/fixtures/worst-case-studio/sanity.cli.ts +16 -0
  82. package/fixtures/worst-case-studio/sanity.config.tsx +49 -0
  83. package/fixtures/worst-case-studio/src/defines.ts +8 -0
  84. package/fixtures/worst-case-studio/src/descriptionIcon.svg +7 -0
  85. package/fixtures/worst-case-studio/src/descriptionInput.module.css +13 -0
  86. package/fixtures/worst-case-studio/src/descriptionInput.tsx +55 -0
  87. package/fixtures/worst-case-studio/src/schemaTypes/author.ts +52 -0
  88. package/fixtures/worst-case-studio/src/schemaTypes/blockContent.ts +70 -0
  89. package/fixtures/worst-case-studio/src/schemaTypes/category.ts +20 -0
  90. package/fixtures/worst-case-studio/src/schemaTypes/index.ts +6 -0
  91. package/fixtures/worst-case-studio/src/schemaTypes/post.ts +71 -0
  92. package/fixtures/worst-case-studio/src/typings.d.ts +37 -0
  93. package/fixtures/worst-case-studio/tsconfig.json +22 -0
  94. package/package.json +52 -22
  95. package/dist/test/captureOutput.d.ts +0 -33
  96. package/dist/test/mockApi.d.ts +0 -34
  97. package/dist/test/testCommand.d.ts +0 -6
  98. package/dist/test/testHook.d.ts +0 -8
package/dist/index.d.ts CHANGED
@@ -1,3 +1,516 @@
1
- export * from './test/mockApi.js';
2
- export * from './test/testCommand.js';
3
- export * from './test/testHook.js';
1
+ import {CliConfig} from '@sanity/cli-core'
2
+ import {ClientConfig} from '@sanity/client'
3
+ import {CLITelemetryStore} from '@sanity/cli-core'
4
+ import {Command} from '@oclif/core'
5
+ import {Config} from '@oclif/core'
6
+ import {Errors} from '@oclif/core'
7
+ import {Hook} from '@oclif/core/hooks'
8
+ import {Hooks} from '@oclif/core/hooks'
9
+ import nock from 'nock'
10
+ import {ProjectRootResult} from '@sanity/cli-core'
11
+ import {SanityClient} from '@sanity/client'
12
+ import {SanityCommand} from '@sanity/cli-core'
13
+ import {TestProject} from 'vitest/node'
14
+ import {vi} from 'vitest'
15
+
16
+ declare interface CaptureOptions {
17
+ /**
18
+ * Whether to print the output to the console
19
+ */
20
+ print?: boolean
21
+ /**
22
+ * Whether to strip ANSI escape codes from the output
23
+ */
24
+ stripAnsi?: boolean
25
+ testNodeEnv?: string
26
+ }
27
+
28
+ declare interface CaptureResult<T = unknown> {
29
+ stderr: string
30
+ stdout: string
31
+ error?: Error & Partial<Errors.CLIError>
32
+ result?: T
33
+ }
34
+
35
+ declare type CommandClass = (new (argv: string[], config: Config) => Command) & typeof Command
36
+
37
+ /**
38
+ * Converts Unix-style paths to platform-appropriate paths.
39
+ * On Windows:
40
+ * - Absolute paths starting with '/': adds drive letter and converts to backslashes
41
+ * - Relative/partial paths: converts forward slashes to backslashes
42
+ * On Unix: keeps paths as-is.
43
+ *
44
+ * @param pathStr - Unix-style path (e.g., '/test/path' or '.config/file.json')
45
+ * @returns Platform-appropriate path
46
+ * @internal
47
+ */
48
+ export declare function convertToSystemPath(pathStr: string): string
49
+
50
+ /**
51
+ * Creates a real Sanity client instance for testing that makes actual HTTP requests.
52
+ * Use with mockApi() to intercept and mock the HTTP calls.
53
+ *
54
+ * @public
55
+ *
56
+ * @example
57
+ * ```typescript
58
+ * // Mock getGlobalCliClient to return a test client
59
+ * vi.mock('@sanity/cli-core', async (importOriginal) => {
60
+ * const actual = await importOriginal<typeof import('@sanity/cli-core')>()
61
+ * const {createTestClient} = await import('@sanity/cli-test')
62
+ *
63
+ * return {
64
+ * ...actual,
65
+ * getGlobalCliClient: vi.fn().mockImplementation((opts) => {
66
+ * return Promise.resolve(createTestClient({
67
+ * apiVersion: opts.apiVersion,
68
+ * }))
69
+ * }),
70
+ * }
71
+ * })
72
+ *
73
+ * // Then use mockApi to intercept requests
74
+ * mockApi({
75
+ * apiVersion: 'v2025-02-19',
76
+ * method: 'get',
77
+ * uri: '/media-libraries',
78
+ * }).reply(200, {data: [...]})
79
+ * ```
80
+ */
81
+ export declare function createTestClient(options: CreateTestClientOptions): {
82
+ client: SanityClient
83
+ request: ReturnType<typeof vi.fn>
84
+ }
85
+
86
+ /**
87
+ * Options for createTestClient
88
+ *
89
+ * @public
90
+ */
91
+ export declare interface CreateTestClientOptions extends ClientConfig {
92
+ /**
93
+ * API version for the client
94
+ */
95
+ apiVersion: string
96
+ /**
97
+ * Authentication token
98
+ */
99
+ token: string
100
+ }
101
+
102
+ /**
103
+ * Creates a test token for the Sanity CLI
104
+ *
105
+ * @public
106
+ *
107
+ * @param token - The token to create
108
+ * @returns void
109
+ */
110
+ export declare function createTestToken(token: string): void
111
+
112
+ /**
113
+ * Default fixtures bundled with the package and their options.
114
+ *
115
+ * @public
116
+ */
117
+ export declare const DEFAULT_FIXTURES: Record<FixtureName, FixtureOptions>
118
+
119
+ /**
120
+ * @deprecated Use {@link FixtureName} instead. This type alias will be removed in a future release.
121
+ * @public
122
+ */
123
+ export declare type ExampleName = FixtureName
124
+
125
+ /**
126
+ * Valid fixture name type.
127
+ * @public
128
+ */
129
+ export declare type FixtureName =
130
+ | 'basic-app'
131
+ | 'basic-studio'
132
+ | 'multi-workspace-studio'
133
+ | 'prebuilt-app'
134
+ | 'prebuilt-studio'
135
+ | 'worst-case-studio'
136
+
137
+ /**
138
+ * Options for each fixture.
139
+ * @public
140
+ */
141
+ export declare interface FixtureOptions {
142
+ includeDist?: boolean
143
+ }
144
+
145
+ /**
146
+ * Gets the current Windows drive letter from process.cwd().
147
+ * Falls back to 'C:\\' if detection fails.
148
+ *
149
+ * @returns Drive letter with backslash (e.g., 'C:\\', 'D:\\') or empty string on Unix
150
+ * @internal
151
+ */
152
+ export declare function getCurrentDrive(): string
153
+
154
+ /**
155
+ * Gets the path to the fixtures directory bundled with this package.
156
+ *
157
+ * The fixtures are copied during build and bundled with the published package.
158
+ * This function works the same whether the package is used in a monorepo
159
+ * or installed from npm.
160
+ *
161
+ * @returns Absolute path to the fixtures directory
162
+ * @internal
163
+ */
164
+ export declare function getFixturesPath(): string
165
+
166
+ /**
167
+ * Gets the path to the temporary directory for test fixtures.
168
+ *
169
+ * Uses the initial working directory captured when this module was first loaded,
170
+ * not process.cwd() which may change during test execution.
171
+ *
172
+ * @param customTempDir - Optional custom temp directory path
173
+ * @returns Absolute path to temp directory (default: initial cwd/tmp)
174
+ * @internal
175
+ */
176
+ export declare function getTempPath(customTempDir?: string): string
177
+
178
+ /**
179
+ * Mocks the API calls, add some defaults so it doesn't cause too much friction
180
+ *
181
+ * @internal
182
+ */
183
+ export declare function mockApi({
184
+ apiHost,
185
+ apiVersion,
186
+ includeQueryTag,
187
+ method,
188
+ projectId,
189
+ query,
190
+ uri,
191
+ }: MockApiOptions): nock.Interceptor
192
+
193
+ /**
194
+ * @internal
195
+ */
196
+ export declare interface MockApiOptions {
197
+ /**
198
+ * Uri to mock
199
+ */
200
+ uri: string
201
+ /**
202
+ * Api host to mock, defaults to `https://api.sanity.io`
203
+ */
204
+ apiHost?: string
205
+ /**
206
+ * Api version to mock, defaults to `v2025-05-14`
207
+ */
208
+ apiVersion?: string
209
+ /**
210
+ * Whether to include `tag: 'sanity.cli'` in query parameters.
211
+ * Defaults to `true`. Set to `false` for endpoints that don't use CLI tagging.
212
+ */
213
+ includeQueryTag?: boolean
214
+ /**
215
+ * HTTP method to mock
216
+ *
217
+ * Defaults to 'get'
218
+ */
219
+ method?: 'delete' | 'get' | 'patch' | 'post' | 'put'
220
+ /**
221
+ * Project ID to mock. When provided, constructs apiHost as `https://{projectId}.api.sanity.io`
222
+ * Takes precedence over apiHost if both are provided.
223
+ */
224
+ projectId?: string
225
+ /**
226
+ * Query parameters to mock
227
+ */
228
+ query?: Record<string, string>
229
+ }
230
+
231
+ /**
232
+ * Creates a testable subclass of a command with mocked SanityCommand dependencies.
233
+ *
234
+ * @public
235
+ *
236
+ * @example
237
+ * ```ts
238
+ * // Basic config mocking
239
+ * const TestAdd = mockSanityCommand(Add, {
240
+ * cliConfig: { api: { projectId: 'test-project' } }
241
+ * })
242
+ *
243
+ * // With mock API client
244
+ * const mockClient = {
245
+ * getDocument: vi.fn().mockResolvedValue({ _id: 'doc1', title: 'Test' }),
246
+ * fetch: vi.fn().mockResolvedValue([]),
247
+ * }
248
+ * const TestGet = mockSanityCommand(GetDocumentCommand, {
249
+ * cliConfig: { api: { projectId: 'test-project', dataset: 'production' } },
250
+ * projectApiClient: mockClient,
251
+ * })
252
+ *
253
+ * const {stdout} = await testCommand(TestGet, ['doc1'])
254
+ * expect(mockClient.getDocument).toHaveBeenCalledWith('doc1')
255
+ * ```
256
+ */
257
+ export declare function mockSanityCommand<T extends typeof SanityCommand<typeof Command>>(
258
+ CommandClass: T,
259
+ options?: MockSanityCommandOptions,
260
+ ): T
261
+
262
+ /**
263
+ * @public
264
+ */
265
+ export declare interface MockSanityCommandOptions {
266
+ /**
267
+ * Mock CLI config (required if command uses getCliConfig or getProjectId)
268
+ */
269
+ cliConfig?: CliConfig
270
+ /**
271
+ * Mock whether the terminal is interactive (used by isUnattended)
272
+ */
273
+ isInteractive?: boolean
274
+ /**
275
+ * Mock project root result (required if command uses getProjectRoot)
276
+ */
277
+ projectRoot?: ProjectRootResult
278
+ /**
279
+ * Mock authentication token (passed to API clients, bypasses getCliToken)
280
+ */
281
+ token?: string
282
+ }
283
+
284
+ /**
285
+ * @public
286
+ * @param options - Options for mocking the telemetry store.
287
+ * @returns The mocked telemetry store.
288
+ */
289
+ export declare const mockTelemetry: (options?: MockTelemetryOptions) => CLITelemetryStore
290
+
291
+ /**
292
+ * @public
293
+ */
294
+ export declare interface MockTelemetryOptions {
295
+ trace?: () => void
296
+ updateUserProperties?: () => void
297
+ }
298
+
299
+ declare interface Options {
300
+ config: Config
301
+ Command?: Command.Class
302
+ context?: Hook.Context
303
+ }
304
+
305
+ /**
306
+ * Global setup function for initializing test fixtures.
307
+ *
308
+ * Copies fixtures from the bundled location to a temp directory
309
+ * and installs dependencies.
310
+ *
311
+ * Note: Fixtures are NOT built during setup. Tests that need built
312
+ * fixtures should build them as part of the test.
313
+ *
314
+ * This function is designed to be used with vitest globalSetup.
315
+ *
316
+ * @public
317
+ *
318
+ * @param options - Configuration options
319
+ * @example
320
+ * ```typescript
321
+ * // In vitest.config.ts
322
+ * export default defineConfig({
323
+ * test: {
324
+ * globalSetup: ['@sanity/cli-test/vitest']
325
+ * }
326
+ * })
327
+ * ```
328
+ */
329
+ export declare function setup(_: TestProject, options?: SetupTestFixturesOptions): Promise<void>
330
+
331
+ /**
332
+ * Options for setupTestFixtures
333
+ *
334
+ * @public
335
+ */
336
+ export declare interface SetupTestFixturesOptions {
337
+ /**
338
+ * Glob patterns for additional fixture directories to set up.
339
+ *
340
+ * Each pattern is matched against directories in the current working directory.
341
+ * Only directories containing a `package.json` file are included.
342
+ *
343
+ * @example
344
+ * ```typescript
345
+ * ['fixtures/*', 'dev/*']
346
+ * ```
347
+ */
348
+ additionalFixtures?: string[]
349
+ /**
350
+ * Custom temp directory path. Defaults to process.cwd()/tmp
351
+ */
352
+ tempDir?: string
353
+ }
354
+
355
+ /**
356
+ * Teardown function to clean up test fixtures.
357
+ *
358
+ * Removes the temp directory created by setupTestFixtures.
359
+ *
360
+ * This function is designed to be used with vitest globalSetup.
361
+ *
362
+ * @public
363
+ *
364
+ * @param options - Configuration options
365
+ */
366
+ export declare function teardown(options?: TeardownTestFixturesOptions): Promise<void>
367
+
368
+ /**
369
+ * Options for teardownTestFixtures
370
+ *
371
+ * @public
372
+ */
373
+ export declare interface TeardownTestFixturesOptions {
374
+ /**
375
+ * Custom temp directory path. Defaults to process.cwd()/tmp
376
+ */
377
+ tempDir?: string
378
+ }
379
+
380
+ /**
381
+ * @public
382
+ */
383
+ export declare function testCommand(
384
+ command: CommandClass,
385
+ args?: string[],
386
+ options?: TestCommandOptions,
387
+ ): Promise<CaptureResult<unknown>>
388
+
389
+ /**
390
+ * @public
391
+ */
392
+ export declare interface TestCommandOptions {
393
+ /**
394
+ * Options for capturing output
395
+ */
396
+ capture?: CaptureOptions
397
+ /**
398
+ * Partial oclif config overrides
399
+ */
400
+ config?: Partial<Config>
401
+ /**
402
+ * Mock options for SanityCommand dependencies (config, project root, API clients).
403
+ * When provided, the command is automatically wrapped with mockSanityCommand.
404
+ */
405
+ mocks?: MockSanityCommandOptions & MockTelemetryOptions
406
+ }
407
+
408
+ /**
409
+ * Recursively copy a directory, skipping specified folders.
410
+ *
411
+ * @param srcDir - Source directory to copy from
412
+ * @param destDir - Destination directory to copy to
413
+ * @param skip - Array of directory/file names to skip (e.g., ['node_modules', 'dist'])
414
+ * @internal
415
+ */
416
+ export declare function testCopyDirectory(
417
+ srcDir: string,
418
+ destDir: string,
419
+ skip?: string[],
420
+ ): Promise<void>
421
+
422
+ /**
423
+ * @deprecated Use {@link testFixture} instead. This function will be removed in a future release.
424
+ *
425
+ * Clones an example (now called fixture) directory into a temporary directory with an isolated copy.
426
+ *
427
+ * @param exampleName - The name of the example/fixture to clone (e.g., 'basic-app', 'basic-studio')
428
+ * @param options - Configuration options
429
+ * @returns The absolute path to the temporary directory containing the example/fixture
430
+ *
431
+ * @public
432
+ */
433
+ export declare function testExample(
434
+ exampleName: FixtureName | (string & {}),
435
+ options?: TestFixtureOptions,
436
+ ): Promise<string>
437
+
438
+ /**
439
+ * @deprecated Use {@link TestFixtureOptions} instead. This type alias will be removed in a future release.
440
+ * @public
441
+ */
442
+ export declare type TestExampleOptions = TestFixtureOptions
443
+
444
+ /**
445
+ * Clones a fixture directory into a temporary directory with an isolated copy.
446
+ *
447
+ * The function creates a unique temporary copy of the specified fixture with:
448
+ * - A random unique ID to avoid conflicts between parallel tests
449
+ * - Symlinked node_modules for performance (from the global setup version)
450
+ * - Modified package.json name to prevent conflicts
451
+ *
452
+ * The fixture is first looked up in the temp directory (if global setup ran),
453
+ * otherwise it falls back to the bundled fixtures in the package.
454
+ *
455
+ * @param fixtureName - The name of the fixture to clone (e.g., 'basic-app', 'basic-studio')
456
+ * @param options - Configuration options
457
+ * @returns The absolute path to the temporary directory containing the fixture
458
+ *
459
+ * @public
460
+ *
461
+ * @example
462
+ * ```typescript
463
+ * import {testFixture} from '@sanity/cli-test'
464
+ * import {describe, test} from 'vitest'
465
+ *
466
+ * describe('my test suite', () => {
467
+ * test('should work with basic-studio', async () => {
468
+ * const cwd = await testFixture('basic-studio')
469
+ * // ... run your tests in this directory
470
+ * })
471
+ * })
472
+ * ```
473
+ */
474
+ export declare function testFixture(
475
+ fixtureName: FixtureName | (string & {}),
476
+ options?: TestFixtureOptions,
477
+ ): Promise<string>
478
+
479
+ /**
480
+ * @public
481
+ */
482
+ export declare interface TestFixtureOptions {
483
+ /**
484
+ * Custom temp directory. Defaults to process.cwd()/tmp
485
+ */
486
+ tempDir?: string
487
+ }
488
+
489
+ /**
490
+ * Test an oclif hook
491
+ *
492
+ * @public
493
+ *
494
+ * @example
495
+ * ```ts
496
+ * const result = await testHook(hook, {
497
+ * Command: Command.loadable,
498
+ * context: {
499
+ * config: Config.load({
500
+ * // CLI root is the directory of the package that contains the hook.
501
+ * root: path.resolve(fileURLToPath(import.meta.url), '../../../root'),
502
+ * }),
503
+ * },
504
+ * })
505
+ * ```
506
+ *
507
+ * @param hook - The hook to test
508
+ * @param options - The options for the hook
509
+ * @returns The result of the hook
510
+ */
511
+ export declare function testHook<T extends keyof Hooks>(
512
+ hook: Hook<T>,
513
+ options: Options,
514
+ ): Promise<CaptureResult<Hooks[T]['return']>>
515
+
516
+ export {}
package/dist/index.js CHANGED
@@ -1,5 +1,13 @@
1
+ export * from './test/constants.js';
2
+ export * from './test/createTestClient.js';
3
+ export * from './test/createTestToken.js';
1
4
  export * from './test/mockApi.js';
5
+ export * from './test/mockSanityCommand.js';
6
+ export * from './test/mockTelemetry.js';
7
+ export * from './test/setupFixtures.js';
2
8
  export * from './test/testCommand.js';
9
+ export * from './test/testFixture.js';
3
10
  export * from './test/testHook.js';
11
+ export * from './utils/paths.js';
4
12
 
5
13
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export * from './test/mockApi.js'\nexport * from './test/testCommand.js'\nexport * from './test/testHook.js'\n"],"names":[],"mappings":"AAAA,cAAc,oBAAmB;AACjC,cAAc,wBAAuB;AACrC,cAAc,qBAAoB"}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export * from './test/constants.js'\nexport * from './test/createTestClient.js'\nexport * from './test/createTestToken.js'\nexport * from './test/mockApi.js'\nexport * from './test/mockSanityCommand.js'\nexport * from './test/mockTelemetry.js'\nexport * from './test/setupFixtures.js'\nexport * from './test/testCommand.js'\nexport * from './test/testFixture.js'\nexport * from './test/testHook.js'\nexport * from './utils/paths.js'\n"],"names":[],"mappings":"AAAA,cAAc,sBAAqB;AACnC,cAAc,6BAA4B;AAC1C,cAAc,4BAA2B;AACzC,cAAc,oBAAmB;AACjC,cAAc,8BAA6B;AAC3C,cAAc,0BAAyB;AACvC,cAAc,0BAAyB;AACvC,cAAc,wBAAuB;AACrC,cAAc,wBAAuB;AACrC,cAAc,qBAAoB;AAClC,cAAc,mBAAkB"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Options for each fixture.
3
+ * @public
4
+ */ /**
5
+ * Default fixtures bundled with the package and their options.
6
+ *
7
+ * @public
8
+ */ export const DEFAULT_FIXTURES = {
9
+ 'basic-app': {},
10
+ 'basic-studio': {},
11
+ 'multi-workspace-studio': {},
12
+ 'prebuilt-app': {
13
+ includeDist: true
14
+ },
15
+ 'prebuilt-studio': {
16
+ includeDist: true
17
+ },
18
+ 'worst-case-studio': {}
19
+ };
20
+
21
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/test/constants.ts"],"sourcesContent":["/**\n * Options for each fixture.\n * @public\n */\nexport interface FixtureOptions {\n includeDist?: boolean\n}\n\n/**\n * Default fixtures bundled with the package and their options.\n *\n * @public\n */\nexport const DEFAULT_FIXTURES: Record<FixtureName, FixtureOptions> = {\n 'basic-app': {},\n 'basic-studio': {},\n 'multi-workspace-studio': {},\n 'prebuilt-app': {includeDist: true},\n 'prebuilt-studio': {includeDist: true},\n 'worst-case-studio': {},\n} as const\n\n/**\n * Valid fixture name type.\n * @public\n */\nexport type FixtureName =\n | 'basic-app'\n | 'basic-studio'\n | 'multi-workspace-studio'\n | 'prebuilt-app'\n | 'prebuilt-studio'\n | 'worst-case-studio'\n\n/**\n * @deprecated Use {@link FixtureName} instead. This type alias will be removed in a future release.\n * @public\n */\nexport type ExampleName = FixtureName\n"],"names":["DEFAULT_FIXTURES","includeDist"],"mappings":"AAAA;;;CAGC,GAKD;;;;CAIC,GACD,OAAO,MAAMA,mBAAwD;IACnE,aAAa,CAAC;IACd,gBAAgB,CAAC;IACjB,0BAA0B,CAAC;IAC3B,gBAAgB;QAACC,aAAa;IAAI;IAClC,mBAAmB;QAACA,aAAa;IAAI;IACrC,qBAAqB,CAAC;AACxB,EAAU"}
@@ -0,0 +1,53 @@
1
+ import { createClient } from '@sanity/client';
2
+ import { vi } from 'vitest';
3
+ /**
4
+ * Creates a real Sanity client instance for testing that makes actual HTTP requests.
5
+ * Use with mockApi() to intercept and mock the HTTP calls.
6
+ *
7
+ * @public
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * // Mock getGlobalCliClient to return a test client
12
+ * vi.mock('@sanity/cli-core', async (importOriginal) => {
13
+ * const actual = await importOriginal<typeof import('@sanity/cli-core')>()
14
+ * const {createTestClient} = await import('@sanity/cli-test')
15
+ *
16
+ * return {
17
+ * ...actual,
18
+ * getGlobalCliClient: vi.fn().mockImplementation((opts) => {
19
+ * return Promise.resolve(createTestClient({
20
+ * apiVersion: opts.apiVersion,
21
+ * }))
22
+ * }),
23
+ * }
24
+ * })
25
+ *
26
+ * // Then use mockApi to intercept requests
27
+ * mockApi({
28
+ * apiVersion: 'v2025-02-19',
29
+ * method: 'get',
30
+ * uri: '/media-libraries',
31
+ * }).reply(200, {data: [...]})
32
+ * ```
33
+ */ export function createTestClient(options) {
34
+ const { apiVersion, projectId, token, ...rest } = options;
35
+ const client = createClient({
36
+ apiVersion,
37
+ projectId,
38
+ requestTagPrefix: 'sanity.cli',
39
+ token,
40
+ useCdn: false,
41
+ useProjectHostname: projectId ? true : false,
42
+ ...rest
43
+ });
44
+ /**
45
+ * Mock the request method of the client to return the actual response from the client
46
+ */ const request = vi.fn((...args)=>client.request(...args));
47
+ return {
48
+ client,
49
+ request
50
+ };
51
+ }
52
+
53
+ //# sourceMappingURL=createTestClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/test/createTestClient.ts"],"sourcesContent":["import {type ClientConfig, createClient, type SanityClient} from '@sanity/client'\nimport {vi} from 'vitest'\n\n/**\n * Options for createTestClient\n *\n * @public\n */\nexport interface CreateTestClientOptions extends ClientConfig {\n /**\n * API version for the client\n */\n apiVersion: string\n\n /**\n * Authentication token\n */\n token: string\n}\n\n/**\n * Creates a real Sanity client instance for testing that makes actual HTTP requests.\n * Use with mockApi() to intercept and mock the HTTP calls.\n *\n * @public\n *\n * @example\n * ```typescript\n * // Mock getGlobalCliClient to return a test client\n * vi.mock('@sanity/cli-core', async (importOriginal) => {\n * const actual = await importOriginal<typeof import('@sanity/cli-core')>()\n * const {createTestClient} = await import('@sanity/cli-test')\n *\n * return {\n * ...actual,\n * getGlobalCliClient: vi.fn().mockImplementation((opts) => {\n * return Promise.resolve(createTestClient({\n * apiVersion: opts.apiVersion,\n * }))\n * }),\n * }\n * })\n *\n * // Then use mockApi to intercept requests\n * mockApi({\n * apiVersion: 'v2025-02-19',\n * method: 'get',\n * uri: '/media-libraries',\n * }).reply(200, {data: [...]})\n * ```\n */\nexport function createTestClient(options: CreateTestClientOptions): {\n client: SanityClient\n request: ReturnType<typeof vi.fn>\n} {\n const {apiVersion, projectId, token, ...rest} = options\n\n const client = createClient({\n apiVersion,\n projectId,\n requestTagPrefix: 'sanity.cli',\n token,\n useCdn: false,\n useProjectHostname: projectId ? true : false,\n ...rest,\n })\n\n /**\n * Mock the request method of the client to return the actual response from the client\n */\n const request = vi.fn((...args: Parameters<typeof client.request>) => client.request(...args))\n\n return {\n client,\n request,\n }\n}\n"],"names":["createClient","vi","createTestClient","options","apiVersion","projectId","token","rest","client","requestTagPrefix","useCdn","useProjectHostname","request","fn","args"],"mappings":"AAAA,SAA2BA,YAAY,QAA0B,iBAAgB;AACjF,SAAQC,EAAE,QAAO,SAAQ;AAmBzB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8BC,GACD,OAAO,SAASC,iBAAiBC,OAAgC;IAI/D,MAAM,EAACC,UAAU,EAAEC,SAAS,EAAEC,KAAK,EAAE,GAAGC,MAAK,GAAGJ;IAEhD,MAAMK,SAASR,aAAa;QAC1BI;QACAC;QACAI,kBAAkB;QAClBH;QACAI,QAAQ;QACRC,oBAAoBN,YAAY,OAAO;QACvC,GAAGE,IAAI;IACT;IAEA;;GAEC,GACD,MAAMK,UAAUX,GAAGY,EAAE,CAAC,CAAC,GAAGC,OAA4CN,OAAOI,OAAO,IAAIE;IAExF,OAAO;QACLN;QACAI;IACF;AACF"}
@@ -0,0 +1,13 @@
1
+ import { vi } from 'vitest';
2
+ /**
3
+ * Creates a test token for the Sanity CLI
4
+ *
5
+ * @public
6
+ *
7
+ * @param token - The token to create
8
+ * @returns void
9
+ */ export function createTestToken(token) {
10
+ vi.stubEnv('SANITY_AUTH_TOKEN', token);
11
+ }
12
+
13
+ //# sourceMappingURL=createTestToken.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/test/createTestToken.ts"],"sourcesContent":["import {vi} from 'vitest'\n\n/**\n * Creates a test token for the Sanity CLI\n *\n * @public\n *\n * @param token - The token to create\n * @returns void\n */\nexport function createTestToken(token: string) {\n vi.stubEnv('SANITY_AUTH_TOKEN', token)\n}\n"],"names":["vi","createTestToken","token","stubEnv"],"mappings":"AAAA,SAAQA,EAAE,QAAO,SAAQ;AAEzB;;;;;;;CAOC,GACD,OAAO,SAASC,gBAAgBC,KAAa;IAC3CF,GAAGG,OAAO,CAAC,qBAAqBD;AAClC"}
@@ -3,12 +3,14 @@ import nock from 'nock';
3
3
  * Mocks the API calls, add some defaults so it doesn't cause too much friction
4
4
  *
5
5
  * @internal
6
- */ export function mockApi({ apiHost = 'https://api.sanity.io', apiVersion = 'v2025-05-14', method = 'get', query = {}, uri }) {
6
+ */ export function mockApi({ apiHost = 'https://api.sanity.io', apiVersion = 'v2025-05-14', includeQueryTag = true, method = 'get', projectId, query = {}, uri }) {
7
7
  const version = apiVersion.startsWith('v') ? apiVersion : `v${apiVersion}`;
8
- return nock(apiHost)[method](`/${version}${uri}`).query({
8
+ const host = projectId ? `https://${projectId}.api.sanity.io` : apiHost;
9
+ const queryParams = includeQueryTag ? {
9
10
  tag: 'sanity.cli',
10
11
  ...query
11
- });
12
+ } : query;
13
+ return nock(host)[method](`/${version}${uri}`).query(queryParams);
12
14
  }
13
15
 
14
16
  //# sourceMappingURL=mockApi.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/test/mockApi.ts"],"sourcesContent":["import nock from 'nock'\n\n/**\n * @internal\n */\nexport interface MockApiOptions {\n /**\n * Uri to mock\n */\n uri: string\n\n /**\n * Api host to mock, defaults to `https://api.sanity.io`\n */\n apiHost?: string\n\n /**\n * Api version to mock, defaults to `v2025-05-14`\n */\n apiVersion?: string\n\n /**\n * HTTP method to mock\n *\n * Defaults to 'get'\n */\n method?: 'delete' | 'get' | 'patch' | 'post' | 'put'\n\n /**\n * Query parameters to mock\n */\n query?: Record<string, string>\n}\n\n/**\n * Mocks the API calls, add some defaults so it doesn't cause too much friction\n *\n * @internal\n */\nexport function mockApi({\n apiHost = 'https://api.sanity.io',\n apiVersion = 'v2025-05-14',\n method = 'get',\n query = {},\n uri,\n}: MockApiOptions) {\n const version = apiVersion.startsWith('v') ? apiVersion : `v${apiVersion}`\n\n return nock(apiHost)\n [method](`/${version}${uri}`)\n .query({tag: 'sanity.cli', ...query})\n}\n"],"names":["nock","mockApi","apiHost","apiVersion","method","query","uri","version","startsWith","tag"],"mappings":"AAAA,OAAOA,UAAU,OAAM;AAkCvB;;;;CAIC,GACD,OAAO,SAASC,QAAQ,EACtBC,UAAU,uBAAuB,EACjCC,aAAa,aAAa,EAC1BC,SAAS,KAAK,EACdC,QAAQ,CAAC,CAAC,EACVC,GAAG,EACY;IACf,MAAMC,UAAUJ,WAAWK,UAAU,CAAC,OAAOL,aAAa,CAAC,CAAC,EAAEA,YAAY;IAE1E,OAAOH,KAAKE,QACV,CAACE,OAAO,CAAC,CAAC,CAAC,EAAEG,UAAUD,KAAK,EAC3BD,KAAK,CAAC;QAACI,KAAK;QAAc,GAAGJ,KAAK;IAAA;AACvC"}
1
+ {"version":3,"sources":["../../src/test/mockApi.ts"],"sourcesContent":["import nock from 'nock'\n\n/**\n * @internal\n */\nexport interface MockApiOptions {\n /**\n * Uri to mock\n */\n uri: string\n\n /**\n * Api host to mock, defaults to `https://api.sanity.io`\n */\n apiHost?: string\n\n /**\n * Api version to mock, defaults to `v2025-05-14`\n */\n apiVersion?: string\n\n /**\n * Whether to include `tag: 'sanity.cli'` in query parameters.\n * Defaults to `true`. Set to `false` for endpoints that don't use CLI tagging.\n */\n includeQueryTag?: boolean\n\n /**\n * HTTP method to mock\n *\n * Defaults to 'get'\n */\n method?: 'delete' | 'get' | 'patch' | 'post' | 'put'\n\n /**\n * Project ID to mock. When provided, constructs apiHost as `https://{projectId}.api.sanity.io`\n * Takes precedence over apiHost if both are provided.\n */\n projectId?: string\n\n /**\n * Query parameters to mock\n */\n query?: Record<string, string>\n}\n\n/**\n * Mocks the API calls, add some defaults so it doesn't cause too much friction\n *\n * @internal\n */\nexport function mockApi({\n apiHost = 'https://api.sanity.io',\n apiVersion = 'v2025-05-14',\n includeQueryTag = true,\n method = 'get',\n projectId,\n query = {},\n uri,\n}: MockApiOptions) {\n const version = apiVersion.startsWith('v') ? apiVersion : `v${apiVersion}`\n const host = projectId ? `https://${projectId}.api.sanity.io` : apiHost\n const queryParams = includeQueryTag ? {tag: 'sanity.cli', ...query} : query\n\n return nock(host)[method](`/${version}${uri}`).query(queryParams)\n}\n"],"names":["nock","mockApi","apiHost","apiVersion","includeQueryTag","method","projectId","query","uri","version","startsWith","host","queryParams","tag"],"mappings":"AAAA,OAAOA,UAAU,OAAM;AA8CvB;;;;CAIC,GACD,OAAO,SAASC,QAAQ,EACtBC,UAAU,uBAAuB,EACjCC,aAAa,aAAa,EAC1BC,kBAAkB,IAAI,EACtBC,SAAS,KAAK,EACdC,SAAS,EACTC,QAAQ,CAAC,CAAC,EACVC,GAAG,EACY;IACf,MAAMC,UAAUN,WAAWO,UAAU,CAAC,OAAOP,aAAa,CAAC,CAAC,EAAEA,YAAY;IAC1E,MAAMQ,OAAOL,YAAY,CAAC,QAAQ,EAAEA,UAAU,cAAc,CAAC,GAAGJ;IAChE,MAAMU,cAAcR,kBAAkB;QAACS,KAAK;QAAc,GAAGN,KAAK;IAAA,IAAIA;IAEtE,OAAOP,KAAKW,KAAK,CAACN,OAAO,CAAC,CAAC,CAAC,EAAEI,UAAUD,KAAK,EAAED,KAAK,CAACK;AACvD"}