@sanity/cli 6.0.0-alpha.4 → 6.0.0-alpha.5
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/actions/dev/startStudioDevServer.js +3 -8
- package/dist/actions/dev/startStudioDevServer.js.map +1 -1
- package/dist/actions/dev/types.d.ts +1 -3
- package/dist/actions/dev/types.js.map +1 -1
- package/dist/actions/documents/validate.d.ts +0 -2
- package/dist/actions/documents/validate.js +21 -1
- package/dist/actions/documents/validate.js.map +1 -1
- package/dist/actions/exec/execScript.js +1 -1
- package/dist/actions/exec/execScript.js.map +1 -1
- package/dist/actions/graphql/__tests__/getGraphQLAPIs.test.js +1 -1
- package/dist/actions/graphql/__tests__/getGraphQLAPIs.test.js.map +1 -1
- package/dist/actions/graphql/getGraphQLAPIs.js +1 -1
- package/dist/actions/graphql/getGraphQLAPIs.js.map +1 -1
- package/dist/actions/manifest/extractManifest.js +1 -4
- package/dist/actions/manifest/extractManifest.js.map +1 -1
- package/dist/actions/schema/deleteSchemaAction.d.ts +13 -5
- package/dist/actions/schema/deleteSchemaAction.js +12 -17
- package/dist/actions/schema/deleteSchemaAction.js.map +1 -1
- package/dist/actions/schema/deploySchemas.d.ts +15 -0
- package/dist/actions/schema/deploySchemas.js +98 -0
- package/dist/actions/schema/deploySchemas.js.map +1 -0
- package/dist/actions/schema/listSchemas.d.ts +12 -0
- package/dist/actions/schema/listSchemas.js +119 -0
- package/dist/actions/schema/listSchemas.js.map +1 -0
- package/dist/actions/schema/schemaStoreTypes.d.ts +0 -11
- package/dist/actions/schema/schemaStoreTypes.js.map +1 -1
- package/dist/actions/schema/utils/debug.d.ts +2 -0
- package/dist/actions/schema/utils/debug.js +5 -0
- package/dist/actions/schema/utils/debug.js.map +1 -0
- package/dist/actions/schema/utils/manifestExtractor.d.ts +3 -8
- package/dist/actions/schema/utils/manifestExtractor.js +12 -17
- package/dist/actions/schema/utils/manifestExtractor.js.map +1 -1
- package/dist/actions/schema/utils/manifestReader.d.ts +2 -9
- package/dist/actions/schema/utils/manifestReader.js +6 -12
- package/dist/actions/schema/utils/manifestReader.js.map +1 -1
- package/dist/actions/schema/utils/schemaStoreOutStrings.d.ts +0 -1
- package/dist/actions/schema/utils/schemaStoreOutStrings.js +1 -1
- package/dist/actions/schema/utils/schemaStoreOutStrings.js.map +1 -1
- package/dist/actions/schema/utils/schemaStoreValidation.d.ts +10 -62
- package/dist/actions/schema/utils/schemaStoreValidation.js +38 -125
- package/dist/actions/schema/utils/schemaStoreValidation.js.map +1 -1
- package/dist/actions/schema/utils/uniqByProjectIdDataset.d.ts +14 -0
- package/dist/actions/schema/utils/uniqByProjectIdDataset.js +9 -0
- package/dist/actions/schema/utils/uniqByProjectIdDataset.js.map +1 -0
- package/dist/actions/users/getMembersForProject.d.ts +1 -3
- package/dist/actions/users/getMembersForProject.js +6 -17
- package/dist/actions/users/getMembersForProject.js.map +1 -1
- package/dist/actions/users/types.d.ts +0 -11
- package/dist/actions/users/types.js.map +1 -1
- package/dist/commands/__tests__/debug.test.js +113 -220
- package/dist/commands/__tests__/debug.test.js.map +1 -1
- package/dist/commands/__tests__/deploy.test.js +325 -293
- package/dist/commands/__tests__/deploy.test.js.map +1 -1
- package/dist/commands/__tests__/dev.test.js +62 -19
- package/dist/commands/__tests__/dev.test.js.map +1 -1
- package/dist/commands/__tests__/init/init.authentication.test.js +40 -27
- package/dist/commands/__tests__/init/init.authentication.test.js.map +1 -1
- package/dist/commands/__tests__/init/init.create-new-project.test.js +84 -85
- package/dist/commands/__tests__/init/init.create-new-project.test.js.map +1 -1
- package/dist/commands/__tests__/init/init.plan.test.js +103 -44
- package/dist/commands/__tests__/init/init.plan.test.js.map +1 -1
- package/dist/commands/__tests__/init/init.setup.test.js +85 -29
- package/dist/commands/__tests__/init/init.setup.test.js.map +1 -1
- package/dist/commands/__tests__/install.test.js +46 -22
- package/dist/commands/__tests__/install.test.js.map +1 -1
- package/dist/commands/__tests__/logout.test.js +8 -5
- package/dist/commands/__tests__/logout.test.js.map +1 -1
- package/dist/commands/__tests__/manage.test.js +29 -24
- package/dist/commands/__tests__/manage.test.js.map +1 -1
- package/dist/commands/__tests__/versions.test.js +22 -14
- package/dist/commands/__tests__/versions.test.js.map +1 -1
- package/dist/commands/backup/__tests__/disable.test.js +72 -75
- package/dist/commands/backup/__tests__/disable.test.js.map +1 -1
- package/dist/commands/backup/__tests__/download.test.js +166 -77
- package/dist/commands/backup/__tests__/download.test.js.map +1 -1
- package/dist/commands/backup/__tests__/enable.test.js +109 -140
- package/dist/commands/backup/__tests__/enable.test.js.map +1 -1
- package/dist/commands/backup/__tests__/list.test.js +84 -75
- package/dist/commands/backup/__tests__/list.test.js.map +1 -1
- package/dist/commands/backup/disable.js +5 -11
- package/dist/commands/backup/disable.js.map +1 -1
- package/dist/commands/backup/enable.js +5 -11
- package/dist/commands/backup/enable.js.map +1 -1
- package/dist/commands/backup/list.js +7 -8
- package/dist/commands/backup/list.js.map +1 -1
- package/dist/commands/cors/__tests__/add.test.js +68 -38
- package/dist/commands/cors/__tests__/add.test.js.map +1 -1
- package/dist/commands/cors/__tests__/delete.test.js +52 -37
- package/dist/commands/cors/__tests__/delete.test.js.map +1 -1
- package/dist/commands/cors/__tests__/list.test.js +80 -57
- package/dist/commands/cors/__tests__/list.test.js.map +1 -1
- package/dist/commands/cors/add.js +5 -13
- package/dist/commands/cors/add.js.map +1 -1
- package/dist/commands/cors/delete.js +7 -15
- package/dist/commands/cors/delete.js.map +1 -1
- package/dist/commands/cors/list.js +2 -10
- package/dist/commands/cors/list.js.map +1 -1
- package/dist/commands/dataset/__tests__/copy.test.js +197 -89
- package/dist/commands/dataset/__tests__/copy.test.js.map +1 -1
- package/dist/commands/dataset/__tests__/create.test.js +147 -117
- package/dist/commands/dataset/__tests__/create.test.js.map +1 -1
- package/dist/commands/dataset/__tests__/delete.test.js +75 -68
- package/dist/commands/dataset/__tests__/delete.test.js.map +1 -1
- package/dist/commands/dataset/__tests__/export.test.js +123 -83
- package/dist/commands/dataset/__tests__/export.test.js.map +1 -1
- package/dist/commands/dataset/__tests__/list.test.js +107 -65
- package/dist/commands/dataset/__tests__/list.test.js.map +1 -1
- package/dist/commands/dataset/alias/__tests__/create.test.js +114 -74
- package/dist/commands/dataset/alias/__tests__/create.test.js.map +1 -1
- package/dist/commands/dataset/alias/__tests__/delete.test.js +40 -29
- package/dist/commands/dataset/alias/__tests__/delete.test.js.map +1 -1
- package/dist/commands/dataset/alias/__tests__/link.test.js +114 -74
- package/dist/commands/dataset/alias/__tests__/link.test.js.map +1 -1
- package/dist/commands/dataset/alias/__tests__/unlink.test.js +44 -29
- package/dist/commands/dataset/alias/__tests__/unlink.test.js.map +1 -1
- package/dist/commands/dataset/export.js +4 -4
- package/dist/commands/dataset/export.js.map +1 -1
- package/dist/commands/dataset/visibility/__tests__/get.test.js +48 -67
- package/dist/commands/dataset/visibility/__tests__/get.test.js.map +1 -1
- package/dist/commands/dataset/visibility/__tests__/set.test.js +76 -123
- package/dist/commands/dataset/visibility/__tests__/set.test.js.map +1 -1
- package/dist/commands/dev.js +0 -1
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/docs/__tests__/search.test.js +8 -7
- package/dist/commands/docs/__tests__/search.test.js.map +1 -1
- package/dist/commands/documents/__tests__/create.test.js +328 -265
- package/dist/commands/documents/__tests__/create.test.js.map +1 -1
- package/dist/commands/documents/__tests__/delete.test.js +119 -87
- package/dist/commands/documents/__tests__/delete.test.js.map +1 -1
- package/dist/commands/documents/__tests__/get.test.js +68 -95
- package/dist/commands/documents/__tests__/get.test.js.map +1 -1
- package/dist/commands/documents/__tests__/query.test.js +84 -189
- package/dist/commands/documents/__tests__/query.test.js.map +1 -1
- package/dist/commands/documents/__tests__/validate.test.js +52 -29
- package/dist/commands/documents/__tests__/validate.test.js.map +1 -1
- package/dist/commands/documents/create.d.ts +1 -0
- package/dist/commands/documents/create.js +10 -9
- package/dist/commands/documents/create.js.map +1 -1
- package/dist/commands/documents/delete.js +2 -3
- package/dist/commands/documents/delete.js.map +1 -1
- package/dist/commands/documents/get.js +2 -3
- package/dist/commands/documents/get.js.map +1 -1
- package/dist/commands/documents/query.js +2 -3
- package/dist/commands/documents/query.js.map +1 -1
- package/dist/commands/documents/validate.js +0 -20
- package/dist/commands/documents/validate.js.map +1 -1
- package/dist/commands/graphql/__tests__/list.test.js +57 -45
- package/dist/commands/graphql/__tests__/list.test.js.map +1 -1
- package/dist/commands/graphql/__tests__/undeploy.test.js +85 -59
- package/dist/commands/graphql/__tests__/undeploy.test.js.map +1 -1
- package/dist/commands/graphql/list.js +2 -2
- package/dist/commands/graphql/list.js.map +1 -1
- package/dist/commands/graphql/undeploy.js +4 -9
- package/dist/commands/graphql/undeploy.js.map +1 -1
- package/dist/commands/hook/__tests__/attempt.test.js +48 -33
- package/dist/commands/hook/__tests__/attempt.test.js.map +1 -1
- package/dist/commands/hook/__tests__/create.test.js +49 -51
- package/dist/commands/hook/__tests__/create.test.js.map +1 -1
- package/dist/commands/hook/__tests__/delete.test.js +43 -30
- package/dist/commands/hook/__tests__/delete.test.js.map +1 -1
- package/dist/commands/hook/__tests__/list.test.js +38 -31
- package/dist/commands/hook/__tests__/list.test.js.map +1 -1
- package/dist/commands/hook/__tests__/logs.test.js +68 -40
- package/dist/commands/hook/__tests__/logs.test.js.map +1 -1
- package/dist/commands/hook/create.js +2 -6
- package/dist/commands/hook/create.js.map +1 -1
- package/dist/commands/hook/delete.js +5 -17
- package/dist/commands/hook/delete.js.map +1 -1
- package/dist/commands/hook/list.js +2 -8
- package/dist/commands/hook/list.js.map +1 -1
- package/dist/commands/manifest/__tests__/extract.test.js +22 -13
- package/dist/commands/manifest/__tests__/extract.test.js.map +1 -1
- package/dist/commands/media/__tests__/create-aspect.test.js +41 -28
- package/dist/commands/media/__tests__/create-aspect.test.js.map +1 -1
- package/dist/commands/media/__tests__/delete-aspect.test.js +44 -35
- package/dist/commands/media/__tests__/delete-aspect.test.js.map +1 -1
- package/dist/commands/media/__tests__/deploy-aspect.test.js +67 -80
- package/dist/commands/media/__tests__/deploy-aspect.test.js.map +1 -1
- package/dist/commands/media/__tests__/export.test.js +365 -66
- package/dist/commands/media/__tests__/export.test.js.map +1 -1
- package/dist/commands/media/__tests__/import.test.js +171 -105
- package/dist/commands/media/__tests__/import.test.js.map +1 -1
- package/dist/commands/media/export.js +2 -2
- package/dist/commands/media/export.js.map +1 -1
- package/dist/commands/media/import.js +2 -2
- package/dist/commands/media/import.js.map +1 -1
- package/dist/commands/projects/__tests__/list.test.js +5 -4
- package/dist/commands/projects/__tests__/list.test.js.map +1 -1
- package/dist/commands/projects/list.js +2 -6
- package/dist/commands/projects/list.js.map +1 -1
- package/dist/commands/schema/__tests__/delete.test.js +396 -151
- package/dist/commands/schema/__tests__/delete.test.js.map +1 -1
- package/dist/commands/schema/__tests__/deploy.test.js +348 -0
- package/dist/commands/schema/__tests__/deploy.test.js.map +1 -0
- package/dist/commands/schema/__tests__/extract.test.js +19 -11
- package/dist/commands/schema/__tests__/extract.test.js.map +1 -1
- package/dist/commands/schema/__tests__/list.test.js +399 -0
- package/dist/commands/schema/__tests__/list.test.js.map +1 -0
- package/dist/commands/schema/__tests__/validate.test.js +27 -10
- package/dist/commands/schema/__tests__/validate.test.js.map +1 -1
- package/dist/commands/schema/delete.d.ts +1 -1
- package/dist/commands/schema/delete.js +20 -23
- package/dist/commands/schema/delete.js.map +1 -1
- package/dist/commands/schema/deploy.d.ts +16 -0
- package/dist/commands/schema/deploy.js +98 -0
- package/dist/commands/schema/deploy.js.map +1 -0
- package/dist/commands/schema/list.d.ts +15 -0
- package/dist/commands/schema/list.js +104 -0
- package/dist/commands/schema/list.js.map +1 -0
- package/dist/commands/telemetry/__tests__/disable.test.js +7 -5
- package/dist/commands/telemetry/__tests__/disable.test.js.map +1 -1
- package/dist/commands/telemetry/__tests__/enable.test.js +7 -5
- package/dist/commands/telemetry/__tests__/enable.test.js.map +1 -1
- package/dist/commands/telemetry/__tests__/status.test.js +7 -5
- package/dist/commands/telemetry/__tests__/status.test.js.map +1 -1
- package/dist/commands/tokens/__tests__/add.test.js +55 -40
- package/dist/commands/tokens/__tests__/add.test.js.map +1 -1
- package/dist/commands/tokens/__tests__/delete.test.js +72 -42
- package/dist/commands/tokens/__tests__/delete.test.js.map +1 -1
- package/dist/commands/tokens/__tests__/list.test.js +87 -60
- package/dist/commands/tokens/__tests__/list.test.js.map +1 -1
- package/dist/commands/tokens/add.js +3 -5
- package/dist/commands/tokens/add.js.map +1 -1
- package/dist/commands/users/__tests__/invite.test.js +100 -79
- package/dist/commands/users/__tests__/invite.test.js.map +1 -1
- package/dist/commands/users/__tests__/list.test.js +186 -180
- package/dist/commands/users/__tests__/list.test.js.map +1 -1
- package/dist/commands/users/invite.js +6 -17
- package/dist/commands/users/invite.js.map +1 -1
- package/dist/commands/users/list.js +4 -7
- package/dist/commands/users/list.js.map +1 -1
- package/dist/config/createCliConfig.d.ts +4 -4
- package/dist/services/backup.d.ts +8 -0
- package/dist/services/backup.js +19 -0
- package/dist/services/backup.js.map +1 -1
- package/dist/services/cors.d.ts +23 -0
- package/dist/services/cors.js +38 -0
- package/dist/services/cors.js.map +1 -0
- package/dist/services/graphql.d.ts +7 -0
- package/dist/services/graphql.js +11 -0
- package/dist/services/graphql.js.map +1 -1
- package/dist/services/hooks.d.ts +2 -0
- package/dist/services/hooks.js +19 -0
- package/dist/services/hooks.js.map +1 -1
- package/dist/services/organizations.d.ts +1 -1
- package/dist/services/organizations.js +1 -1
- package/dist/services/organizations.js.map +1 -1
- package/dist/services/projects.d.ts +11 -0
- package/dist/services/projects.js +41 -0
- package/dist/services/projects.js.map +1 -1
- package/dist/services/schemas.d.ts +4 -0
- package/dist/services/schemas.js +40 -0
- package/dist/services/schemas.js.map +1 -0
- package/dist/services/user.d.ts +8 -0
- package/dist/services/user.js +15 -2
- package/dist/services/user.js.map +1 -1
- package/dist/util/__tests__/getCliVersion.test.js +2 -2
- package/dist/util/__tests__/getCliVersion.test.js.map +1 -1
- package/dist/util/errorMessages.d.ts +1 -0
- package/dist/util/errorMessages.js +1 -0
- package/dist/util/errorMessages.js.map +1 -1
- package/dist/util/getCliVersion.js +1 -1
- package/dist/util/getCliVersion.js.map +1 -1
- package/dist/util/readPackageJson.d.ts +1 -15
- package/dist/util/readPackageJson.js +1 -1
- package/dist/util/readPackageJson.js.map +1 -1
- package/dist/util/uniqBy.d.ts +1 -0
- package/dist/util/uniqBy.js +14 -0
- package/dist/util/uniqBy.js.map +1 -0
- package/oclif.manifest.json +172 -27
- package/package.json +27 -28
- package/dist/actions/cors/constants.d.ts +0 -1
- package/dist/actions/cors/constants.js +0 -3
- package/dist/actions/cors/constants.js.map +0 -1
- package/dist/actions/cors/types.d.ts +0 -9
- package/dist/actions/cors/types.js +0 -3
- package/dist/actions/cors/types.js.map +0 -1
- package/dist/actions/schema/__tests__/deleteSchemaAction.test.js +0 -294
- package/dist/actions/schema/__tests__/deleteSchemaAction.test.js.map +0 -1
- package/dist/actions/schema/schemaStoreConstants.d.ts +0 -1
- package/dist/actions/schema/schemaStoreConstants.js +0 -4
- package/dist/actions/schema/schemaStoreConstants.js.map +0 -1
- package/dist/actions/schema/utils/schemaActionHelpers.d.ts +0 -1
- package/dist/actions/schema/utils/schemaActionHelpers.js +0 -5
- package/dist/actions/schema/utils/schemaActionHelpers.js.map +0 -1
- package/dist/actions/schema/utils/schemaApiClient.d.ts +0 -6
- package/dist/actions/schema/utils/schemaApiClient.js +0 -17
- package/dist/actions/schema/utils/schemaApiClient.js.map +0 -1
- package/dist/actions/users/apiVersion.d.ts +0 -6
- package/dist/actions/users/apiVersion.js +0 -7
- package/dist/actions/users/apiVersion.js.map +0 -1
|
@@ -1,28 +1,31 @@
|
|
|
1
1
|
import { runCommand } from '@oclif/test';
|
|
2
2
|
import { select } from '@sanity/cli-core/ux';
|
|
3
|
-
import { testCommand } from '@sanity/cli-test';
|
|
3
|
+
import { createTestClient, mockApi, testCommand } from '@sanity/cli-test';
|
|
4
|
+
import nock from 'nock';
|
|
4
5
|
import { of, throwError } from 'rxjs';
|
|
5
6
|
import { afterEach, describe, expect, test, vi } from 'vitest';
|
|
6
|
-
import {
|
|
7
|
-
import * as datasetsService from '../../../services/datasets.js';
|
|
7
|
+
import { DATASET_API_VERSION, followCopyJobProgress } from '../../../services/datasets.js';
|
|
8
8
|
import { CopyDatasetCommand } from '../copy.js';
|
|
9
|
-
vi.
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
9
|
+
const mockListDatasets = vi.hoisted(()=>vi.fn());
|
|
10
|
+
const testProjectId = vi.hoisted(()=>'test-project');
|
|
11
|
+
const testToken = vi.hoisted(()=>'test-token');
|
|
12
|
+
vi.mock('@sanity/cli-core', async (importOriginal)=>{
|
|
13
|
+
const actual = await importOriginal();
|
|
14
|
+
const testClient = createTestClient({
|
|
15
|
+
apiVersion: 'v2025-09-16',
|
|
16
|
+
projectId: testProjectId,
|
|
17
|
+
token: testToken
|
|
18
|
+
});
|
|
19
|
+
return {
|
|
20
|
+
...actual,
|
|
21
|
+
getProjectCliClient: vi.fn().mockResolvedValue({
|
|
22
|
+
datasets: {
|
|
23
|
+
list: mockListDatasets
|
|
24
|
+
},
|
|
25
|
+
request: testClient.request
|
|
21
26
|
})
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
getCliToken: vi.fn().mockResolvedValue('test-token')
|
|
25
|
-
}));
|
|
27
|
+
};
|
|
28
|
+
});
|
|
26
29
|
vi.mock('@sanity/cli-core/ux', async ()=>{
|
|
27
30
|
const actual = await vi.importActual('@sanity/cli-core/ux');
|
|
28
31
|
return {
|
|
@@ -31,19 +34,29 @@ vi.mock('@sanity/cli-core/ux', async ()=>{
|
|
|
31
34
|
select: vi.fn()
|
|
32
35
|
};
|
|
33
36
|
});
|
|
34
|
-
vi.mock('../../../services/datasets.js', ()=>
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
37
|
+
vi.mock('../../../services/datasets.js', async (importOriginal)=>{
|
|
38
|
+
const actual = await importOriginal();
|
|
39
|
+
return {
|
|
40
|
+
...actual,
|
|
41
|
+
// Keep only followCopyJobProgress mocked since it uses EventSource streaming
|
|
42
|
+
followCopyJobProgress: vi.fn()
|
|
43
|
+
};
|
|
44
|
+
});
|
|
45
|
+
const defaultMocks = {
|
|
46
|
+
cliConfig: {
|
|
47
|
+
api: {
|
|
48
|
+
projectId: testProjectId
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
projectRoot: {
|
|
52
|
+
directory: '/test/path',
|
|
53
|
+
path: '/test/path/sanity.config.ts',
|
|
54
|
+
type: 'studio'
|
|
55
|
+
},
|
|
56
|
+
token: testToken
|
|
57
|
+
};
|
|
41
58
|
const mockSelect = vi.mocked(select);
|
|
42
|
-
const
|
|
43
|
-
const mockFollowCopyJobProgress = vi.mocked(datasetsService.followCopyJobProgress);
|
|
44
|
-
const mockListDatasetCopyJobs = vi.mocked(datasetsService.listDatasetCopyJobs);
|
|
45
|
-
const mockListDatasets = vi.mocked(datasetsService.listDatasets);
|
|
46
|
-
// Helper to create mock datasets
|
|
59
|
+
const mockFollowCopyJobProgress = vi.mocked(followCopyJobProgress);
|
|
47
60
|
function createMockDataset(name) {
|
|
48
61
|
return {
|
|
49
62
|
aclMode: 'public',
|
|
@@ -59,6 +72,9 @@ function createMockDataset(name) {
|
|
|
59
72
|
describe('#dataset:copy', ()=>{
|
|
60
73
|
afterEach(()=>{
|
|
61
74
|
vi.clearAllMocks();
|
|
75
|
+
const pending = nock.pendingMocks();
|
|
76
|
+
nock.cleanAll();
|
|
77
|
+
expect(pending, 'pending mocks').toEqual([]);
|
|
62
78
|
});
|
|
63
79
|
test('help works', async ()=>{
|
|
64
80
|
const { stdout } = await runCommand([
|
|
@@ -126,7 +142,12 @@ describe('#dataset:copy', ()=>{
|
|
|
126
142
|
});
|
|
127
143
|
describe('list mode', ()=>{
|
|
128
144
|
test('lists copy jobs successfully', async ()=>{
|
|
129
|
-
|
|
145
|
+
mockApi({
|
|
146
|
+
apiHost: `https://${testProjectId}.api.sanity.io`,
|
|
147
|
+
apiVersion: DATASET_API_VERSION,
|
|
148
|
+
method: 'get',
|
|
149
|
+
uri: `/projects/${testProjectId}/datasets/copy`
|
|
150
|
+
}).reply(200, [
|
|
130
151
|
{
|
|
131
152
|
createdAt: '2023-01-01T00:00:00Z',
|
|
132
153
|
id: 'job-1',
|
|
@@ -148,11 +169,8 @@ describe('#dataset:copy', ()=>{
|
|
|
148
169
|
]);
|
|
149
170
|
const { stdout } = await testCommand(CopyDatasetCommand, [
|
|
150
171
|
'--list'
|
|
151
|
-
]
|
|
152
|
-
|
|
153
|
-
limit: undefined,
|
|
154
|
-
offset: undefined,
|
|
155
|
-
projectId: 'test-project'
|
|
172
|
+
], {
|
|
173
|
+
mocks: defaultMocks
|
|
156
174
|
});
|
|
157
175
|
expect(stdout).toContain('Dataset copy jobs');
|
|
158
176
|
expect(stdout).toContain('job-1');
|
|
@@ -161,33 +179,79 @@ describe('#dataset:copy', ()=>{
|
|
|
161
179
|
expect(stdout).toContain('staging');
|
|
162
180
|
});
|
|
163
181
|
test('lists copy jobs with offset and limit', async ()=>{
|
|
164
|
-
|
|
165
|
-
|
|
182
|
+
mockApi({
|
|
183
|
+
apiHost: `https://${testProjectId}.api.sanity.io`,
|
|
184
|
+
apiVersion: DATASET_API_VERSION,
|
|
185
|
+
method: 'get',
|
|
186
|
+
query: {
|
|
187
|
+
limit: '10',
|
|
188
|
+
offset: '2'
|
|
189
|
+
},
|
|
190
|
+
uri: `/projects/${testProjectId}/datasets/copy`
|
|
191
|
+
}).reply(200, [
|
|
192
|
+
{
|
|
193
|
+
createdAt: '2023-01-01T00:00:00Z',
|
|
194
|
+
id: 'job-2',
|
|
195
|
+
sourceDataset: 'production',
|
|
196
|
+
state: 'completed',
|
|
197
|
+
targetDataset: 'backup',
|
|
198
|
+
updatedAt: '2023-01-01T00:05:00Z',
|
|
199
|
+
withHistory: true
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
createdAt: '2023-01-02T00:00:00Z',
|
|
203
|
+
id: 'job-3',
|
|
204
|
+
sourceDataset: 'staging',
|
|
205
|
+
state: 'failed',
|
|
206
|
+
targetDataset: 'test',
|
|
207
|
+
updatedAt: '2023-01-02T00:02:00Z',
|
|
208
|
+
withHistory: false
|
|
209
|
+
}
|
|
210
|
+
]);
|
|
211
|
+
const { stdout } = await testCommand(CopyDatasetCommand, [
|
|
166
212
|
'--list',
|
|
167
213
|
'--offset',
|
|
168
214
|
'2',
|
|
169
215
|
'--limit',
|
|
170
216
|
'10'
|
|
171
|
-
]
|
|
172
|
-
|
|
173
|
-
limit: 10,
|
|
174
|
-
offset: 2,
|
|
175
|
-
projectId: 'test-project'
|
|
217
|
+
], {
|
|
218
|
+
mocks: defaultMocks
|
|
176
219
|
});
|
|
220
|
+
expect(stdout).toContain('job-2');
|
|
221
|
+
expect(stdout).toContain('job-3');
|
|
222
|
+
expect(stdout).toContain('production');
|
|
223
|
+
expect(stdout).toContain('staging');
|
|
177
224
|
});
|
|
178
225
|
test('shows message when no copy jobs exist', async ()=>{
|
|
179
|
-
|
|
226
|
+
mockApi({
|
|
227
|
+
apiHost: `https://${testProjectId}.api.sanity.io`,
|
|
228
|
+
apiVersion: DATASET_API_VERSION,
|
|
229
|
+
method: 'get',
|
|
230
|
+
uri: `/projects/${testProjectId}/datasets/copy`
|
|
231
|
+
}).reply(200, []);
|
|
180
232
|
const { stdout } = await testCommand(CopyDatasetCommand, [
|
|
181
233
|
'--list'
|
|
182
|
-
]
|
|
234
|
+
], {
|
|
235
|
+
mocks: defaultMocks
|
|
236
|
+
});
|
|
183
237
|
expect(stdout).toContain("This project doesn't have any dataset copy jobs");
|
|
184
238
|
});
|
|
185
239
|
test('handles errors when listing copy jobs', async ()=>{
|
|
186
|
-
|
|
240
|
+
mockApi({
|
|
241
|
+
apiHost: `https://${testProjectId}.api.sanity.io`,
|
|
242
|
+
apiVersion: DATASET_API_VERSION,
|
|
243
|
+
method: 'get',
|
|
244
|
+
uri: `/projects/${testProjectId}/datasets/copy`
|
|
245
|
+
}).reply(500, {
|
|
246
|
+
error: 'API Error',
|
|
247
|
+
message: 'API Error'
|
|
248
|
+
});
|
|
187
249
|
const { error } = await testCommand(CopyDatasetCommand, [
|
|
188
250
|
'--list'
|
|
189
|
-
]
|
|
190
|
-
|
|
251
|
+
], {
|
|
252
|
+
mocks: defaultMocks
|
|
253
|
+
});
|
|
254
|
+
expect(error?.message).toContain('Failed to list dataset copy jobs');
|
|
191
255
|
expect(error?.oclif?.exit).toBe(1);
|
|
192
256
|
});
|
|
193
257
|
});
|
|
@@ -209,7 +273,9 @@ describe('#dataset:copy', ()=>{
|
|
|
209
273
|
const { stdout } = await testCommand(CopyDatasetCommand, [
|
|
210
274
|
'--attach',
|
|
211
275
|
'job-123'
|
|
212
|
-
]
|
|
276
|
+
], {
|
|
277
|
+
mocks: defaultMocks
|
|
278
|
+
});
|
|
213
279
|
expect(mockFollowCopyJobProgress).toHaveBeenCalledWith({
|
|
214
280
|
jobId: 'job-123',
|
|
215
281
|
projectId: 'test-project'
|
|
@@ -221,7 +287,9 @@ describe('#dataset:copy', ()=>{
|
|
|
221
287
|
const { error } = await testCommand(CopyDatasetCommand, [
|
|
222
288
|
'--attach',
|
|
223
289
|
'job-123'
|
|
224
|
-
]
|
|
290
|
+
], {
|
|
291
|
+
mocks: defaultMocks
|
|
292
|
+
});
|
|
225
293
|
expect(error?.message).toContain('Failed to attach to copy job: Connection lost');
|
|
226
294
|
expect(error?.oclif?.exit).toBe(1);
|
|
227
295
|
});
|
|
@@ -229,7 +297,9 @@ describe('#dataset:copy', ()=>{
|
|
|
229
297
|
const { error } = await testCommand(CopyDatasetCommand, [
|
|
230
298
|
'--attach',
|
|
231
299
|
' '
|
|
232
|
-
]
|
|
300
|
+
], {
|
|
301
|
+
mocks: defaultMocks
|
|
302
|
+
});
|
|
233
303
|
expect(error?.message).toContain('Please supply a valid jobId');
|
|
234
304
|
expect(error?.oclif?.exit).toBe(1);
|
|
235
305
|
});
|
|
@@ -238,7 +308,9 @@ describe('#dataset:copy', ()=>{
|
|
|
238
308
|
const { error } = await testCommand(CopyDatasetCommand, [
|
|
239
309
|
'--attach',
|
|
240
310
|
'job-123'
|
|
241
|
-
]
|
|
311
|
+
], {
|
|
312
|
+
mocks: defaultMocks
|
|
313
|
+
});
|
|
242
314
|
expect(error?.message).toContain('Invalid JSON received from server');
|
|
243
315
|
expect(error?.oclif?.exit).toBe(1);
|
|
244
316
|
});
|
|
@@ -255,7 +327,9 @@ describe('#dataset:copy', ()=>{
|
|
|
255
327
|
const { stdout } = await testCommand(CopyDatasetCommand, [
|
|
256
328
|
'--attach',
|
|
257
329
|
'job-123'
|
|
258
|
-
]
|
|
330
|
+
], {
|
|
331
|
+
mocks: defaultMocks
|
|
332
|
+
});
|
|
259
333
|
expect(mockFollowCopyJobProgress).toHaveBeenCalledWith({
|
|
260
334
|
jobId: 'job-123',
|
|
261
335
|
projectId: 'test-project'
|
|
@@ -267,7 +341,9 @@ describe('#dataset:copy', ()=>{
|
|
|
267
341
|
const { error } = await testCommand(CopyDatasetCommand, [
|
|
268
342
|
'--attach',
|
|
269
343
|
'job-123'
|
|
270
|
-
]
|
|
344
|
+
], {
|
|
345
|
+
mocks: defaultMocks
|
|
346
|
+
});
|
|
271
347
|
expect(error?.message).toContain('Copy job failed');
|
|
272
348
|
expect(error?.oclif?.exit).toBe(1);
|
|
273
349
|
});
|
|
@@ -278,7 +354,12 @@ describe('#dataset:copy', ()=>{
|
|
|
278
354
|
createMockDataset('production'),
|
|
279
355
|
createMockDataset('staging')
|
|
280
356
|
]);
|
|
281
|
-
|
|
357
|
+
mockApi({
|
|
358
|
+
apiHost: `https://${testProjectId}.api.sanity.io`,
|
|
359
|
+
apiVersion: DATASET_API_VERSION,
|
|
360
|
+
method: 'put',
|
|
361
|
+
uri: `/datasets/production/copy`
|
|
362
|
+
}).reply(200, {
|
|
282
363
|
jobId: 'job-456'
|
|
283
364
|
});
|
|
284
365
|
mockFollowCopyJobProgress.mockReturnValue(of({
|
|
@@ -288,12 +369,8 @@ describe('#dataset:copy', ()=>{
|
|
|
288
369
|
const { stdout } = await testCommand(CopyDatasetCommand, [
|
|
289
370
|
'production',
|
|
290
371
|
'backup'
|
|
291
|
-
]
|
|
292
|
-
|
|
293
|
-
projectId: 'test-project',
|
|
294
|
-
skipHistory: false,
|
|
295
|
-
sourceDataset: 'production',
|
|
296
|
-
targetDataset: 'backup'
|
|
372
|
+
], {
|
|
373
|
+
mocks: defaultMocks
|
|
297
374
|
});
|
|
298
375
|
expect(stdout).toContain('Copying dataset production to backup');
|
|
299
376
|
expect(stdout).toContain('Job job-456 started');
|
|
@@ -306,14 +383,21 @@ describe('#dataset:copy', ()=>{
|
|
|
306
383
|
]);
|
|
307
384
|
mockSelect.mockResolvedValueOnce('production');
|
|
308
385
|
mockSelect.mockResolvedValueOnce('backup');
|
|
309
|
-
|
|
386
|
+
mockApi({
|
|
387
|
+
apiHost: `https://${testProjectId}.api.sanity.io`,
|
|
388
|
+
apiVersion: DATASET_API_VERSION,
|
|
389
|
+
method: 'put',
|
|
390
|
+
uri: `/datasets/production/copy`
|
|
391
|
+
}).reply(200, {
|
|
310
392
|
jobId: 'job-789'
|
|
311
393
|
});
|
|
312
394
|
mockFollowCopyJobProgress.mockReturnValue(of({
|
|
313
395
|
progress: 100,
|
|
314
396
|
type: 'progress'
|
|
315
397
|
}));
|
|
316
|
-
await testCommand(CopyDatasetCommand, []
|
|
398
|
+
await testCommand(CopyDatasetCommand, [], {
|
|
399
|
+
mocks: defaultMocks
|
|
400
|
+
});
|
|
317
401
|
expect(mockSelect).toHaveBeenCalledWith({
|
|
318
402
|
choices: expect.arrayContaining([
|
|
319
403
|
expect.objectContaining({
|
|
@@ -382,7 +466,9 @@ describe('#dataset:copy', ()=>{
|
|
|
382
466
|
}
|
|
383
467
|
])('errors when $description', async ({ args, expectedError, setupMocks })=>{
|
|
384
468
|
setupMocks();
|
|
385
|
-
const { error } = await testCommand(CopyDatasetCommand, args
|
|
469
|
+
const { error } = await testCommand(CopyDatasetCommand, args, {
|
|
470
|
+
mocks: defaultMocks
|
|
471
|
+
});
|
|
386
472
|
expect(error?.message).toContain(expectedError);
|
|
387
473
|
expect(error?.oclif?.exit).toBe(1);
|
|
388
474
|
});
|
|
@@ -391,7 +477,12 @@ describe('#dataset:copy', ()=>{
|
|
|
391
477
|
createMockDataset('production'),
|
|
392
478
|
createMockDataset('staging')
|
|
393
479
|
]);
|
|
394
|
-
|
|
480
|
+
mockApi({
|
|
481
|
+
apiHost: `https://${testProjectId}.api.sanity.io`,
|
|
482
|
+
apiVersion: DATASET_API_VERSION,
|
|
483
|
+
method: 'put',
|
|
484
|
+
uri: `/datasets/production/copy`
|
|
485
|
+
}).reply(200, {
|
|
395
486
|
jobId: 'job-skip'
|
|
396
487
|
});
|
|
397
488
|
mockFollowCopyJobProgress.mockReturnValue(of({
|
|
@@ -402,12 +493,8 @@ describe('#dataset:copy', ()=>{
|
|
|
402
493
|
'production',
|
|
403
494
|
'backup',
|
|
404
495
|
'--skip-history'
|
|
405
|
-
]
|
|
406
|
-
|
|
407
|
-
projectId: 'test-project',
|
|
408
|
-
skipHistory: true,
|
|
409
|
-
sourceDataset: 'production',
|
|
410
|
-
targetDataset: 'backup'
|
|
496
|
+
], {
|
|
497
|
+
mocks: defaultMocks
|
|
411
498
|
});
|
|
412
499
|
});
|
|
413
500
|
test('copies dataset with detach flag (does not wait for completion)', async ()=>{
|
|
@@ -415,19 +502,20 @@ describe('#dataset:copy', ()=>{
|
|
|
415
502
|
createMockDataset('production'),
|
|
416
503
|
createMockDataset('staging')
|
|
417
504
|
]);
|
|
418
|
-
|
|
505
|
+
mockApi({
|
|
506
|
+
apiHost: `https://${testProjectId}.api.sanity.io`,
|
|
507
|
+
apiVersion: DATASET_API_VERSION,
|
|
508
|
+
method: 'put',
|
|
509
|
+
uri: `/datasets/production/copy`
|
|
510
|
+
}).reply(200, {
|
|
419
511
|
jobId: 'job-detach'
|
|
420
512
|
});
|
|
421
513
|
const { stdout } = await testCommand(CopyDatasetCommand, [
|
|
422
514
|
'production',
|
|
423
515
|
'backup',
|
|
424
516
|
'--detach'
|
|
425
|
-
]
|
|
426
|
-
|
|
427
|
-
projectId: 'test-project',
|
|
428
|
-
skipHistory: false,
|
|
429
|
-
sourceDataset: 'production',
|
|
430
|
-
targetDataset: 'backup'
|
|
517
|
+
], {
|
|
518
|
+
mocks: defaultMocks
|
|
431
519
|
});
|
|
432
520
|
expect(stdout).toContain('Job job-detach started');
|
|
433
521
|
expect(stdout).not.toContain('Job job-detach completed');
|
|
@@ -438,12 +526,22 @@ describe('#dataset:copy', ()=>{
|
|
|
438
526
|
createMockDataset('production'),
|
|
439
527
|
createMockDataset('staging')
|
|
440
528
|
]);
|
|
441
|
-
|
|
529
|
+
mockApi({
|
|
530
|
+
apiHost: `https://${testProjectId}.api.sanity.io`,
|
|
531
|
+
apiVersion: DATASET_API_VERSION,
|
|
532
|
+
method: 'put',
|
|
533
|
+
uri: `/datasets/production/copy`
|
|
534
|
+
}).reply(500, {
|
|
535
|
+
error: 'Insufficient permissions',
|
|
536
|
+
message: 'Insufficient permissions'
|
|
537
|
+
});
|
|
442
538
|
const { error } = await testCommand(CopyDatasetCommand, [
|
|
443
539
|
'production',
|
|
444
540
|
'backup'
|
|
445
|
-
]
|
|
446
|
-
|
|
541
|
+
], {
|
|
542
|
+
mocks: defaultMocks
|
|
543
|
+
});
|
|
544
|
+
expect(error?.message).toContain('Dataset copying failed');
|
|
447
545
|
expect(error?.oclif?.exit).toBe(1);
|
|
448
546
|
});
|
|
449
547
|
test('handles fetch datasets error', async ()=>{
|
|
@@ -451,7 +549,9 @@ describe('#dataset:copy', ()=>{
|
|
|
451
549
|
const { error } = await testCommand(CopyDatasetCommand, [
|
|
452
550
|
'production',
|
|
453
551
|
'backup'
|
|
454
|
-
]
|
|
552
|
+
], {
|
|
553
|
+
mocks: defaultMocks
|
|
554
|
+
});
|
|
455
555
|
expect(error?.message).toContain('Failed to fetch datasets: Network error');
|
|
456
556
|
expect(error?.oclif?.exit).toBe(1);
|
|
457
557
|
});
|
|
@@ -482,7 +582,9 @@ describe('#dataset:copy', ()=>{
|
|
|
482
582
|
]
|
|
483
583
|
}
|
|
484
584
|
])('errors when using mutually exclusive flags: $desc', async ({ flags })=>{
|
|
485
|
-
const { error } = await testCommand(CopyDatasetCommand, flags
|
|
585
|
+
const { error } = await testCommand(CopyDatasetCommand, flags, {
|
|
586
|
+
mocks: defaultMocks
|
|
587
|
+
});
|
|
486
588
|
expect(error?.message).toContain('cannot also be provided when using');
|
|
487
589
|
expect(error?.oclif?.exit).toBe(2);
|
|
488
590
|
});
|
|
@@ -499,19 +601,25 @@ describe('#dataset:copy', ()=>{
|
|
|
499
601
|
const { error } = await testCommand(CopyDatasetCommand, [
|
|
500
602
|
flag,
|
|
501
603
|
value
|
|
502
|
-
]
|
|
604
|
+
], {
|
|
605
|
+
mocks: defaultMocks
|
|
606
|
+
});
|
|
503
607
|
expect(error?.message).toContain('--list');
|
|
504
608
|
expect(error?.oclif?.exit).toBe(2);
|
|
505
609
|
});
|
|
506
610
|
});
|
|
507
611
|
test('errors when no project ID is found', async ()=>{
|
|
508
|
-
mockGetCliConfig.mockResolvedValueOnce({
|
|
509
|
-
api: undefined
|
|
510
|
-
});
|
|
511
612
|
const { error } = await testCommand(CopyDatasetCommand, [
|
|
512
613
|
'production',
|
|
513
614
|
'backup'
|
|
514
|
-
]
|
|
615
|
+
], {
|
|
616
|
+
mocks: {
|
|
617
|
+
...defaultMocks,
|
|
618
|
+
cliConfig: {
|
|
619
|
+
api: undefined
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
});
|
|
515
623
|
expect(error?.message).toContain('sanity.cli.ts does not contain a project identifier');
|
|
516
624
|
expect(error?.oclif?.exit).toBe(1);
|
|
517
625
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/commands/dataset/__tests__/copy.test.ts"],"sourcesContent":["import {runCommand} from '@oclif/test'\nimport {select} from '@sanity/cli-core/ux'\nimport {testCommand} from '@sanity/cli-test'\nimport {of, throwError} from 'rxjs'\nimport {afterEach, describe, expect, test, vi} from 'vitest'\n\nimport {getCliConfig} from '../../../../../cli-core/src/config/cli/getCliConfig.js'\nimport * as datasetsService from '../../../services/datasets.js'\nimport {CopyDatasetCommand} from '../copy.js'\n\nvi.mock('../../../../../cli-core/src/config/findProjectRoot.js', () => ({\n findProjectRoot: vi.fn().mockResolvedValue({\n directory: '/test/path',\n root: '/test/path',\n type: 'studio',\n }),\n}))\n\nvi.mock('../../../../../cli-core/src/config/cli/getCliConfig.js', () => ({\n getCliConfig: vi.fn().mockResolvedValue({\n api: {\n projectId: 'test-project',\n },\n }),\n}))\n\nvi.mock('../../../../../cli-core/src/services/getCliToken.js', () => ({\n getCliToken: vi.fn().mockResolvedValue('test-token'),\n}))\n\nvi.mock('@sanity/cli-core/ux', async () => {\n const actual = await vi.importActual<typeof import('@sanity/cli-core/ux')>('@sanity/cli-core/ux')\n return {\n ...actual,\n input: vi.fn(),\n select: vi.fn(),\n }\n})\n\nvi.mock('../../../services/datasets.js', () => ({\n copyDataset: vi.fn(),\n followCopyJobProgress: vi.fn(),\n listDatasetCopyJobs: vi.fn(),\n listDatasets: vi.fn(),\n}))\n\nconst mockGetCliConfig = vi.mocked(getCliConfig)\nconst mockSelect = vi.mocked(select)\nconst mockCopyDataset = vi.mocked(datasetsService.copyDataset)\nconst mockFollowCopyJobProgress = vi.mocked(datasetsService.followCopyJobProgress)\nconst mockListDatasetCopyJobs = vi.mocked(datasetsService.listDatasetCopyJobs)\nconst mockListDatasets = vi.mocked(datasetsService.listDatasets)\n\n// Helper to create mock datasets\nfunction createMockDataset(name: string) {\n return {\n aclMode: 'public' as const,\n addonFor: null,\n createdAt: '2023-01-01T00:00:00Z',\n createdByUserId: 'test-user',\n datasetProfile: 'default',\n features: [],\n name,\n tags: [],\n }\n}\n\ndescribe('#dataset:copy', () => {\n afterEach(() => {\n vi.clearAllMocks()\n })\n\n test('help works', async () => {\n const {stdout} = await runCommand(['dataset copy', '--help'])\n\n expect(stdout).toMatchInlineSnapshot(`\n \"Manages dataset copying, including starting a new copy job, listing copy jobs and following the progress of a running copy job\n\n USAGE\n $ sanity dataset copy [SOURCE] [TARGET] [--attach <value> | --list |\n --detach | --skip-history] [--limit <value> ] [--offset <value> ]\n\n ARGUMENTS\n [SOURCE] Name of the dataset to copy from\n [TARGET] Name of the dataset to copy to\n\n FLAGS\n --attach=<value> Attach to the running copy process to show progress\n --detach Start the copy without waiting for it to finish\n --limit=<value> Maximum number of jobs returned (default 10, max 1000)\n --list Lists all dataset copy jobs\n --offset=<value> Start position in the list of jobs (default 0)\n --skip-history Don't preserve document history on copy\n\n DESCRIPTION\n Manages dataset copying, including starting a new copy job, listing copy jobs\n and following the progress of a running copy job\n\n EXAMPLES\n Interactively copy a dataset\n\n $ sanity dataset copy\n\n Copy from source-dataset (prompts for target)\n\n $ sanity dataset copy source-dataset\n\n Copy from source-dataset to target-dataset\n\n $ sanity dataset copy source-dataset target-dataset\n\n Copy without preserving document history (faster for large datasets)\n\n $ sanity dataset copy --skip-history source target\n\n Start copy job without waiting for completion\n\n $ sanity dataset copy --detach source target\n\n Attach to a running copy job to follow progress\n\n $ sanity dataset copy --attach <job-id>\n\n List all dataset copy jobs\n\n $ sanity dataset copy --list\n\n List copy jobs with pagination\n\n $ sanity dataset copy --list --offset 2 --limit 10\n\n \"\n `)\n })\n\n describe('list mode', () => {\n test('lists copy jobs successfully', async () => {\n mockListDatasetCopyJobs.mockResolvedValue([\n {\n createdAt: '2023-01-01T00:00:00Z',\n id: 'job-1',\n sourceDataset: 'production',\n state: 'completed',\n targetDataset: 'backup',\n updatedAt: '2023-01-01T00:05:00Z',\n withHistory: true,\n },\n {\n createdAt: '2023-01-02T00:00:00Z',\n id: 'job-2',\n sourceDataset: 'staging',\n state: 'failed',\n targetDataset: 'test',\n updatedAt: '2023-01-02T00:02:00Z',\n withHistory: false,\n },\n ])\n\n const {stdout} = await testCommand(CopyDatasetCommand, ['--list'])\n\n expect(mockListDatasetCopyJobs).toHaveBeenCalledWith({\n limit: undefined,\n offset: undefined,\n projectId: 'test-project',\n })\n expect(stdout).toContain('Dataset copy jobs')\n expect(stdout).toContain('job-1')\n expect(stdout).toContain('job-2')\n expect(stdout).toContain('production')\n expect(stdout).toContain('staging')\n })\n\n test('lists copy jobs with offset and limit', async () => {\n mockListDatasetCopyJobs.mockResolvedValue([])\n\n await testCommand(CopyDatasetCommand, ['--list', '--offset', '2', '--limit', '10'])\n\n expect(mockListDatasetCopyJobs).toHaveBeenCalledWith({\n limit: 10,\n offset: 2,\n projectId: 'test-project',\n })\n })\n\n test('shows message when no copy jobs exist', async () => {\n mockListDatasetCopyJobs.mockResolvedValue([])\n\n const {stdout} = await testCommand(CopyDatasetCommand, ['--list'])\n\n expect(stdout).toContain(\"This project doesn't have any dataset copy jobs\")\n })\n\n test('handles errors when listing copy jobs', async () => {\n mockListDatasetCopyJobs.mockRejectedValue(new Error('API Error'))\n\n const {error} = await testCommand(CopyDatasetCommand, ['--list'])\n\n expect(error?.message).toContain('Failed to list dataset copy jobs: API Error')\n expect(error?.oclif?.exit).toBe(1)\n })\n })\n\n describe('attach mode', () => {\n test('attaches to running job and shows progress', async () => {\n mockFollowCopyJobProgress.mockReturnValue(\n of(\n {progress: 25, type: 'progress'},\n {progress: 50, type: 'progress'},\n {progress: 75, type: 'progress'},\n {progress: 100, type: 'progress'},\n ),\n )\n\n const {stdout} = await testCommand(CopyDatasetCommand, ['--attach', 'job-123'])\n\n expect(mockFollowCopyJobProgress).toHaveBeenCalledWith({\n jobId: 'job-123',\n projectId: 'test-project',\n })\n expect(stdout).toContain('Job job-123 completed')\n })\n\n test('handles progress tracking errors', async () => {\n mockFollowCopyJobProgress.mockReturnValue(throwError(() => new Error('Connection lost')))\n\n const {error} = await testCommand(CopyDatasetCommand, ['--attach', 'job-123'])\n\n expect(error?.message).toContain('Failed to attach to copy job: Connection lost')\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test('rejects whitespace-only jobId', async () => {\n const {error} = await testCommand(CopyDatasetCommand, ['--attach', ' '])\n\n expect(error?.message).toContain('Please supply a valid jobId')\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test('handles JSON parse errors from EventSource', async () => {\n mockFollowCopyJobProgress.mockReturnValue(\n throwError(() => new Error('Invalid JSON received from server: Unexpected token')),\n )\n\n const {error} = await testCommand(CopyDatasetCommand, ['--attach', 'job-123'])\n\n expect(error?.message).toContain('Invalid JSON received from server')\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test('handles EventSource reconnection', async () => {\n mockFollowCopyJobProgress.mockReturnValue(\n of({progress: 25, type: 'progress'}, {type: 'reconnect'}, {progress: 50, type: 'progress'}),\n )\n\n const {stdout} = await testCommand(CopyDatasetCommand, ['--attach', 'job-123'])\n\n expect(mockFollowCopyJobProgress).toHaveBeenCalledWith({\n jobId: 'job-123',\n projectId: 'test-project',\n })\n expect(stdout).toContain('Job job-123 completed')\n })\n\n test('handles channel_error from EventSource', async () => {\n mockFollowCopyJobProgress.mockReturnValue(\n throwError(() => new Error('Copy job failed: Channel closed unexpectedly')),\n )\n\n const {error} = await testCommand(CopyDatasetCommand, ['--attach', 'job-123'])\n\n expect(error?.message).toContain('Copy job failed')\n expect(error?.oclif?.exit).toBe(1)\n })\n })\n\n describe('copy mode', () => {\n test('copies dataset with provided arguments', async () => {\n mockListDatasets.mockResolvedValue([\n createMockDataset('production'),\n createMockDataset('staging'),\n ])\n mockCopyDataset.mockResolvedValue({jobId: 'job-456'})\n mockFollowCopyJobProgress.mockReturnValue(of({progress: 100, type: 'progress'}))\n\n const {stdout} = await testCommand(CopyDatasetCommand, ['production', 'backup'])\n\n expect(mockCopyDataset).toHaveBeenCalledWith({\n projectId: 'test-project',\n skipHistory: false,\n sourceDataset: 'production',\n targetDataset: 'backup',\n })\n expect(stdout).toContain('Copying dataset production to backup')\n expect(stdout).toContain('Job job-456 started')\n expect(stdout).toContain('Job job-456 completed')\n })\n\n test('prompts for source dataset when not provided', async () => {\n mockListDatasets.mockResolvedValue([\n createMockDataset('production'),\n createMockDataset('staging'),\n ])\n mockSelect.mockResolvedValueOnce('production')\n mockSelect.mockResolvedValueOnce('backup')\n mockCopyDataset.mockResolvedValue({jobId: 'job-789'})\n mockFollowCopyJobProgress.mockReturnValue(of({progress: 100, type: 'progress'}))\n\n await testCommand(CopyDatasetCommand, [])\n\n expect(mockSelect).toHaveBeenCalledWith({\n choices: expect.arrayContaining([\n expect.objectContaining({value: 'production'}),\n expect.objectContaining({value: 'staging'}),\n ]),\n message: 'Select the dataset name:',\n })\n })\n\n test.each([\n {\n args: ['Invalid-Dataset', 'backup'],\n description: 'source dataset name is invalid',\n expectedError: 'must be all lowercase',\n setupMocks: () => {\n // No additional mocks needed - validation happens before dataset fetch\n },\n },\n {\n args: ['nonexistent', 'backup'],\n description: 'source dataset does not exist',\n expectedError: 'Source dataset \"nonexistent\" doesn\\'t exist',\n setupMocks: () => {\n mockListDatasets.mockResolvedValue([\n createMockDataset('production'),\n createMockDataset('staging'),\n ])\n },\n },\n {\n args: ['production', 'Invalid-Dataset'],\n description: 'target dataset name is invalid',\n expectedError: 'must be all lowercase',\n setupMocks: () => {\n mockListDatasets.mockResolvedValue([\n createMockDataset('production'),\n createMockDataset('staging'),\n ])\n },\n },\n {\n args: ['production', 'staging'],\n description: 'target dataset already exists',\n expectedError: 'Target dataset \"staging\" already exists',\n setupMocks: () => {\n mockListDatasets.mockResolvedValue([\n createMockDataset('production'),\n createMockDataset('staging'),\n ])\n },\n },\n ])('errors when $description', async ({args, expectedError, setupMocks}) => {\n setupMocks()\n\n const {error} = await testCommand(CopyDatasetCommand, args)\n\n expect(error?.message).toContain(expectedError)\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test('copies dataset with skip-history flag', async () => {\n mockListDatasets.mockResolvedValue([\n createMockDataset('production'),\n createMockDataset('staging'),\n ])\n mockCopyDataset.mockResolvedValue({jobId: 'job-skip'})\n mockFollowCopyJobProgress.mockReturnValue(of({progress: 100, type: 'progress'}))\n\n await testCommand(CopyDatasetCommand, ['production', 'backup', '--skip-history'])\n\n expect(mockCopyDataset).toHaveBeenCalledWith({\n projectId: 'test-project',\n skipHistory: true,\n sourceDataset: 'production',\n targetDataset: 'backup',\n })\n })\n\n test('copies dataset with detach flag (does not wait for completion)', async () => {\n mockListDatasets.mockResolvedValue([\n createMockDataset('production'),\n createMockDataset('staging'),\n ])\n mockCopyDataset.mockResolvedValue({jobId: 'job-detach'})\n\n const {stdout} = await testCommand(CopyDatasetCommand, ['production', 'backup', '--detach'])\n\n expect(mockCopyDataset).toHaveBeenCalledWith({\n projectId: 'test-project',\n skipHistory: false,\n sourceDataset: 'production',\n targetDataset: 'backup',\n })\n expect(stdout).toContain('Job job-detach started')\n expect(stdout).not.toContain('Job job-detach completed')\n expect(mockFollowCopyJobProgress).not.toHaveBeenCalled()\n })\n\n test('handles copy dataset errors', async () => {\n mockListDatasets.mockResolvedValue([\n createMockDataset('production'),\n createMockDataset('staging'),\n ])\n mockCopyDataset.mockRejectedValue(new Error('Insufficient permissions'))\n\n const {error} = await testCommand(CopyDatasetCommand, ['production', 'backup'])\n\n expect(error?.message).toContain('Dataset copying failed: Insufficient permissions')\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test('handles fetch datasets error', async () => {\n mockListDatasets.mockRejectedValue(new Error('Network error'))\n\n const {error} = await testCommand(CopyDatasetCommand, ['production', 'backup'])\n\n expect(error?.message).toContain('Failed to fetch datasets: Network error')\n expect(error?.oclif?.exit).toBe(1)\n })\n })\n\n describe('flag validation', () => {\n test.each([\n {desc: '--list with --attach', flags: ['--list', '--attach', 'job-123']},\n {desc: '--list with --detach', flags: ['--list', '--detach']},\n {desc: '--attach with --detach', flags: ['--attach', 'job-123', '--detach']},\n ])('errors when using mutually exclusive flags: $desc', async ({flags}) => {\n const {error} = await testCommand(CopyDatasetCommand, flags)\n\n expect(error?.message).toContain('cannot also be provided when using')\n expect(error?.oclif?.exit).toBe(2)\n })\n\n test.each([\n {flag: '--offset', value: '2'},\n {flag: '--limit', value: '10'},\n ])('errors when $flag is used without --list', async ({flag, value}) => {\n const {error} = await testCommand(CopyDatasetCommand, [flag, value])\n\n expect(error?.message).toContain('--list')\n expect(error?.oclif?.exit).toBe(2)\n })\n })\n\n test('errors when no project ID is found', async () => {\n mockGetCliConfig.mockResolvedValueOnce({\n api: undefined,\n } as ReturnType<typeof getCliConfig> extends Promise<infer T> ? T : never)\n\n const {error} = await testCommand(CopyDatasetCommand, ['production', 'backup'])\n\n expect(error?.message).toContain('sanity.cli.ts does not contain a project identifier')\n expect(error?.oclif?.exit).toBe(1)\n })\n})\n"],"names":["runCommand","select","testCommand","of","throwError","afterEach","describe","expect","test","vi","getCliConfig","datasetsService","CopyDatasetCommand","mock","findProjectRoot","fn","mockResolvedValue","directory","root","type","api","projectId","getCliToken","actual","importActual","input","copyDataset","followCopyJobProgress","listDatasetCopyJobs","listDatasets","mockGetCliConfig","mocked","mockSelect","mockCopyDataset","mockFollowCopyJobProgress","mockListDatasetCopyJobs","mockListDatasets","createMockDataset","name","aclMode","addonFor","createdAt","createdByUserId","datasetProfile","features","tags","clearAllMocks","stdout","toMatchInlineSnapshot","id","sourceDataset","state","targetDataset","updatedAt","withHistory","toHaveBeenCalledWith","limit","undefined","offset","toContain","mockRejectedValue","Error","error","message","oclif","exit","toBe","mockReturnValue","progress","jobId","skipHistory","mockResolvedValueOnce","choices","arrayContaining","objectContaining","value","each","args","description","expectedError","setupMocks","not","toHaveBeenCalled","desc","flags","flag"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../src/commands/dataset/__tests__/copy.test.ts"],"sourcesContent":["import {runCommand} from '@oclif/test'\nimport {select} from '@sanity/cli-core/ux'\nimport {createTestClient, mockApi, testCommand} from '@sanity/cli-test'\nimport nock from 'nock'\nimport {of, throwError} from 'rxjs'\nimport {afterEach, describe, expect, test, vi} from 'vitest'\n\nimport {DATASET_API_VERSION, followCopyJobProgress} from '../../../services/datasets.js'\nimport {CopyDatasetCommand} from '../copy.js'\n\nconst mockListDatasets = vi.hoisted(() => vi.fn())\nconst testProjectId = vi.hoisted(() => 'test-project')\nconst testToken = vi.hoisted(() => 'test-token')\n\nvi.mock('@sanity/cli-core', async (importOriginal) => {\n const actual = await importOriginal<typeof import('@sanity/cli-core')>()\n const testClient = createTestClient({\n apiVersion: 'v2025-09-16',\n projectId: testProjectId,\n token: testToken,\n })\n\n return {\n ...actual,\n getProjectCliClient: vi.fn().mockResolvedValue({\n datasets: {\n list: mockListDatasets,\n } as never,\n request: testClient.request,\n }),\n }\n})\n\nvi.mock('@sanity/cli-core/ux', async () => {\n const actual = await vi.importActual<typeof import('@sanity/cli-core/ux')>('@sanity/cli-core/ux')\n return {\n ...actual,\n input: vi.fn(),\n select: vi.fn(),\n }\n})\n\nvi.mock('../../../services/datasets.js', async (importOriginal) => {\n const actual = await importOriginal<typeof import('../../../services/datasets.js')>()\n return {\n ...actual,\n // Keep only followCopyJobProgress mocked since it uses EventSource streaming\n followCopyJobProgress: vi.fn(),\n }\n})\n\nconst defaultMocks = {\n cliConfig: {api: {projectId: testProjectId}},\n projectRoot: {\n directory: '/test/path',\n path: '/test/path/sanity.config.ts',\n type: 'studio' as const,\n },\n token: testToken,\n}\n\nconst mockSelect = vi.mocked(select)\nconst mockFollowCopyJobProgress = vi.mocked(followCopyJobProgress)\n\nfunction createMockDataset(name: string) {\n return {\n aclMode: 'public' as const,\n addonFor: null,\n createdAt: '2023-01-01T00:00:00Z',\n createdByUserId: 'test-user',\n datasetProfile: 'default',\n features: [],\n name,\n tags: [],\n }\n}\n\ndescribe('#dataset:copy', () => {\n afterEach(() => {\n vi.clearAllMocks()\n const pending = nock.pendingMocks()\n nock.cleanAll()\n expect(pending, 'pending mocks').toEqual([])\n })\n\n test('help works', async () => {\n const {stdout} = await runCommand(['dataset copy', '--help'])\n\n expect(stdout).toMatchInlineSnapshot(`\n \"Manages dataset copying, including starting a new copy job, listing copy jobs and following the progress of a running copy job\n\n USAGE\n $ sanity dataset copy [SOURCE] [TARGET] [--attach <value> | --list |\n --detach | --skip-history] [--limit <value> ] [--offset <value> ]\n\n ARGUMENTS\n [SOURCE] Name of the dataset to copy from\n [TARGET] Name of the dataset to copy to\n\n FLAGS\n --attach=<value> Attach to the running copy process to show progress\n --detach Start the copy without waiting for it to finish\n --limit=<value> Maximum number of jobs returned (default 10, max 1000)\n --list Lists all dataset copy jobs\n --offset=<value> Start position in the list of jobs (default 0)\n --skip-history Don't preserve document history on copy\n\n DESCRIPTION\n Manages dataset copying, including starting a new copy job, listing copy jobs\n and following the progress of a running copy job\n\n EXAMPLES\n Interactively copy a dataset\n\n $ sanity dataset copy\n\n Copy from source-dataset (prompts for target)\n\n $ sanity dataset copy source-dataset\n\n Copy from source-dataset to target-dataset\n\n $ sanity dataset copy source-dataset target-dataset\n\n Copy without preserving document history (faster for large datasets)\n\n $ sanity dataset copy --skip-history source target\n\n Start copy job without waiting for completion\n\n $ sanity dataset copy --detach source target\n\n Attach to a running copy job to follow progress\n\n $ sanity dataset copy --attach <job-id>\n\n List all dataset copy jobs\n\n $ sanity dataset copy --list\n\n List copy jobs with pagination\n\n $ sanity dataset copy --list --offset 2 --limit 10\n\n \"\n `)\n })\n\n describe('list mode', () => {\n test('lists copy jobs successfully', async () => {\n mockApi({\n apiHost: `https://${testProjectId}.api.sanity.io`,\n apiVersion: DATASET_API_VERSION,\n method: 'get',\n uri: `/projects/${testProjectId}/datasets/copy`,\n }).reply(200, [\n {\n createdAt: '2023-01-01T00:00:00Z',\n id: 'job-1',\n sourceDataset: 'production',\n state: 'completed',\n targetDataset: 'backup',\n updatedAt: '2023-01-01T00:05:00Z',\n withHistory: true,\n },\n {\n createdAt: '2023-01-02T00:00:00Z',\n id: 'job-2',\n sourceDataset: 'staging',\n state: 'failed',\n targetDataset: 'test',\n updatedAt: '2023-01-02T00:02:00Z',\n withHistory: false,\n },\n ])\n\n const {stdout} = await testCommand(CopyDatasetCommand, ['--list'], {mocks: defaultMocks})\n\n expect(stdout).toContain('Dataset copy jobs')\n expect(stdout).toContain('job-1')\n expect(stdout).toContain('job-2')\n expect(stdout).toContain('production')\n expect(stdout).toContain('staging')\n })\n\n test('lists copy jobs with offset and limit', async () => {\n mockApi({\n apiHost: `https://${testProjectId}.api.sanity.io`,\n apiVersion: DATASET_API_VERSION,\n method: 'get',\n query: {\n limit: '10',\n offset: '2',\n },\n uri: `/projects/${testProjectId}/datasets/copy`,\n }).reply(200, [\n {\n createdAt: '2023-01-01T00:00:00Z',\n id: 'job-2',\n sourceDataset: 'production',\n state: 'completed',\n targetDataset: 'backup',\n updatedAt: '2023-01-01T00:05:00Z',\n withHistory: true,\n },\n {\n createdAt: '2023-01-02T00:00:00Z',\n id: 'job-3',\n sourceDataset: 'staging',\n state: 'failed',\n targetDataset: 'test',\n updatedAt: '2023-01-02T00:02:00Z',\n withHistory: false,\n },\n ])\n\n const {stdout} = await testCommand(\n CopyDatasetCommand,\n ['--list', '--offset', '2', '--limit', '10'],\n {\n mocks: defaultMocks,\n },\n )\n\n expect(stdout).toContain('job-2')\n expect(stdout).toContain('job-3')\n expect(stdout).toContain('production')\n expect(stdout).toContain('staging')\n })\n\n test('shows message when no copy jobs exist', async () => {\n mockApi({\n apiHost: `https://${testProjectId}.api.sanity.io`,\n apiVersion: DATASET_API_VERSION,\n method: 'get',\n uri: `/projects/${testProjectId}/datasets/copy`,\n }).reply(200, [])\n\n const {stdout} = await testCommand(CopyDatasetCommand, ['--list'], {mocks: defaultMocks})\n\n expect(stdout).toContain(\"This project doesn't have any dataset copy jobs\")\n })\n\n test('handles errors when listing copy jobs', async () => {\n mockApi({\n apiHost: `https://${testProjectId}.api.sanity.io`,\n apiVersion: DATASET_API_VERSION,\n method: 'get',\n uri: `/projects/${testProjectId}/datasets/copy`,\n }).reply(500, {\n error: 'API Error',\n message: 'API Error',\n })\n\n const {error} = await testCommand(CopyDatasetCommand, ['--list'], {mocks: defaultMocks})\n\n expect(error?.message).toContain('Failed to list dataset copy jobs')\n expect(error?.oclif?.exit).toBe(1)\n })\n })\n\n describe('attach mode', () => {\n test('attaches to running job and shows progress', async () => {\n mockFollowCopyJobProgress.mockReturnValue(\n of(\n {progress: 25, type: 'progress'},\n {progress: 50, type: 'progress'},\n {progress: 75, type: 'progress'},\n {progress: 100, type: 'progress'},\n ),\n )\n\n const {stdout} = await testCommand(CopyDatasetCommand, ['--attach', 'job-123'], {\n mocks: defaultMocks,\n })\n\n expect(mockFollowCopyJobProgress).toHaveBeenCalledWith({\n jobId: 'job-123',\n projectId: 'test-project',\n })\n expect(stdout).toContain('Job job-123 completed')\n })\n\n test('handles progress tracking errors', async () => {\n mockFollowCopyJobProgress.mockReturnValue(throwError(() => new Error('Connection lost')))\n\n const {error} = await testCommand(CopyDatasetCommand, ['--attach', 'job-123'], {\n mocks: defaultMocks,\n })\n\n expect(error?.message).toContain('Failed to attach to copy job: Connection lost')\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test('rejects whitespace-only jobId', async () => {\n const {error} = await testCommand(CopyDatasetCommand, ['--attach', ' '], {\n mocks: defaultMocks,\n })\n\n expect(error?.message).toContain('Please supply a valid jobId')\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test('handles JSON parse errors from EventSource', async () => {\n mockFollowCopyJobProgress.mockReturnValue(\n throwError(() => new Error('Invalid JSON received from server: Unexpected token')),\n )\n\n const {error} = await testCommand(CopyDatasetCommand, ['--attach', 'job-123'], {\n mocks: defaultMocks,\n })\n\n expect(error?.message).toContain('Invalid JSON received from server')\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test('handles EventSource reconnection', async () => {\n mockFollowCopyJobProgress.mockReturnValue(\n of({progress: 25, type: 'progress'}, {type: 'reconnect'}, {progress: 50, type: 'progress'}),\n )\n\n const {stdout} = await testCommand(CopyDatasetCommand, ['--attach', 'job-123'], {\n mocks: defaultMocks,\n })\n\n expect(mockFollowCopyJobProgress).toHaveBeenCalledWith({\n jobId: 'job-123',\n projectId: 'test-project',\n })\n expect(stdout).toContain('Job job-123 completed')\n })\n\n test('handles channel_error from EventSource', async () => {\n mockFollowCopyJobProgress.mockReturnValue(\n throwError(() => new Error('Copy job failed: Channel closed unexpectedly')),\n )\n\n const {error} = await testCommand(CopyDatasetCommand, ['--attach', 'job-123'], {\n mocks: defaultMocks,\n })\n\n expect(error?.message).toContain('Copy job failed')\n expect(error?.oclif?.exit).toBe(1)\n })\n })\n\n describe('copy mode', () => {\n test('copies dataset with provided arguments', async () => {\n mockListDatasets.mockResolvedValue([\n createMockDataset('production'),\n createMockDataset('staging'),\n ])\n mockApi({\n apiHost: `https://${testProjectId}.api.sanity.io`,\n apiVersion: DATASET_API_VERSION,\n method: 'put',\n uri: `/datasets/production/copy`,\n }).reply(200, {jobId: 'job-456'})\n mockFollowCopyJobProgress.mockReturnValue(of({progress: 100, type: 'progress'}))\n\n const {stdout} = await testCommand(CopyDatasetCommand, ['production', 'backup'], {\n mocks: defaultMocks,\n })\n\n expect(stdout).toContain('Copying dataset production to backup')\n expect(stdout).toContain('Job job-456 started')\n expect(stdout).toContain('Job job-456 completed')\n })\n\n test('prompts for source dataset when not provided', async () => {\n mockListDatasets.mockResolvedValue([\n createMockDataset('production'),\n createMockDataset('staging'),\n ])\n mockSelect.mockResolvedValueOnce('production')\n mockSelect.mockResolvedValueOnce('backup')\n mockApi({\n apiHost: `https://${testProjectId}.api.sanity.io`,\n apiVersion: DATASET_API_VERSION,\n method: 'put',\n uri: `/datasets/production/copy`,\n }).reply(200, {jobId: 'job-789'})\n mockFollowCopyJobProgress.mockReturnValue(of({progress: 100, type: 'progress'}))\n\n await testCommand(CopyDatasetCommand, [], {mocks: defaultMocks})\n\n expect(mockSelect).toHaveBeenCalledWith({\n choices: expect.arrayContaining([\n expect.objectContaining({value: 'production'}),\n expect.objectContaining({value: 'staging'}),\n ]),\n message: 'Select the dataset name:',\n })\n })\n\n test.each([\n {\n args: ['Invalid-Dataset', 'backup'],\n description: 'source dataset name is invalid',\n expectedError: 'must be all lowercase',\n setupMocks: () => {\n // No additional mocks needed - validation happens before dataset fetch\n },\n },\n {\n args: ['nonexistent', 'backup'],\n description: 'source dataset does not exist',\n expectedError: 'Source dataset \"nonexistent\" doesn\\'t exist',\n setupMocks: () => {\n mockListDatasets.mockResolvedValue([\n createMockDataset('production'),\n createMockDataset('staging'),\n ])\n },\n },\n {\n args: ['production', 'Invalid-Dataset'],\n description: 'target dataset name is invalid',\n expectedError: 'must be all lowercase',\n setupMocks: () => {\n mockListDatasets.mockResolvedValue([\n createMockDataset('production'),\n createMockDataset('staging'),\n ])\n },\n },\n {\n args: ['production', 'staging'],\n description: 'target dataset already exists',\n expectedError: 'Target dataset \"staging\" already exists',\n setupMocks: () => {\n mockListDatasets.mockResolvedValue([\n createMockDataset('production'),\n createMockDataset('staging'),\n ])\n },\n },\n ])('errors when $description', async ({args, expectedError, setupMocks}) => {\n setupMocks()\n\n const {error} = await testCommand(CopyDatasetCommand, args, {mocks: defaultMocks})\n\n expect(error?.message).toContain(expectedError)\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test('copies dataset with skip-history flag', async () => {\n mockListDatasets.mockResolvedValue([\n createMockDataset('production'),\n createMockDataset('staging'),\n ])\n mockApi({\n apiHost: `https://${testProjectId}.api.sanity.io`,\n apiVersion: DATASET_API_VERSION,\n method: 'put',\n uri: `/datasets/production/copy`,\n }).reply(200, {jobId: 'job-skip'})\n mockFollowCopyJobProgress.mockReturnValue(of({progress: 100, type: 'progress'}))\n\n await testCommand(CopyDatasetCommand, ['production', 'backup', '--skip-history'], {\n mocks: defaultMocks,\n })\n })\n\n test('copies dataset with detach flag (does not wait for completion)', async () => {\n mockListDatasets.mockResolvedValue([\n createMockDataset('production'),\n createMockDataset('staging'),\n ])\n mockApi({\n apiHost: `https://${testProjectId}.api.sanity.io`,\n apiVersion: DATASET_API_VERSION,\n method: 'put',\n uri: `/datasets/production/copy`,\n }).reply(200, {jobId: 'job-detach'})\n\n const {stdout} = await testCommand(CopyDatasetCommand, ['production', 'backup', '--detach'], {\n mocks: defaultMocks,\n })\n\n expect(stdout).toContain('Job job-detach started')\n expect(stdout).not.toContain('Job job-detach completed')\n expect(mockFollowCopyJobProgress).not.toHaveBeenCalled()\n })\n\n test('handles copy dataset errors', async () => {\n mockListDatasets.mockResolvedValue([\n createMockDataset('production'),\n createMockDataset('staging'),\n ])\n mockApi({\n apiHost: `https://${testProjectId}.api.sanity.io`,\n apiVersion: DATASET_API_VERSION,\n method: 'put',\n uri: `/datasets/production/copy`,\n }).reply(500, {\n error: 'Insufficient permissions',\n message: 'Insufficient permissions',\n })\n\n const {error} = await testCommand(CopyDatasetCommand, ['production', 'backup'], {\n mocks: defaultMocks,\n })\n\n expect(error?.message).toContain('Dataset copying failed')\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test('handles fetch datasets error', async () => {\n mockListDatasets.mockRejectedValue(new Error('Network error'))\n\n const {error} = await testCommand(CopyDatasetCommand, ['production', 'backup'], {\n mocks: defaultMocks,\n })\n\n expect(error?.message).toContain('Failed to fetch datasets: Network error')\n expect(error?.oclif?.exit).toBe(1)\n })\n })\n\n describe('flag validation', () => {\n test.each([\n {desc: '--list with --attach', flags: ['--list', '--attach', 'job-123']},\n {desc: '--list with --detach', flags: ['--list', '--detach']},\n {desc: '--attach with --detach', flags: ['--attach', 'job-123', '--detach']},\n ])('errors when using mutually exclusive flags: $desc', async ({flags}) => {\n const {error} = await testCommand(CopyDatasetCommand, flags, {mocks: defaultMocks})\n\n expect(error?.message).toContain('cannot also be provided when using')\n expect(error?.oclif?.exit).toBe(2)\n })\n\n test.each([\n {flag: '--offset', value: '2'},\n {flag: '--limit', value: '10'},\n ])('errors when $flag is used without --list', async ({flag, value}) => {\n const {error} = await testCommand(CopyDatasetCommand, [flag, value], {mocks: defaultMocks})\n\n expect(error?.message).toContain('--list')\n expect(error?.oclif?.exit).toBe(2)\n })\n })\n\n test('errors when no project ID is found', async () => {\n const {error} = await testCommand(CopyDatasetCommand, ['production', 'backup'], {\n mocks: {\n ...defaultMocks,\n cliConfig: {api: undefined},\n },\n })\n\n expect(error?.message).toContain('sanity.cli.ts does not contain a project identifier')\n expect(error?.oclif?.exit).toBe(1)\n })\n})\n"],"names":["runCommand","select","createTestClient","mockApi","testCommand","nock","of","throwError","afterEach","describe","expect","test","vi","DATASET_API_VERSION","followCopyJobProgress","CopyDatasetCommand","mockListDatasets","hoisted","fn","testProjectId","testToken","mock","importOriginal","actual","testClient","apiVersion","projectId","token","getProjectCliClient","mockResolvedValue","datasets","list","request","importActual","input","defaultMocks","cliConfig","api","projectRoot","directory","path","type","mockSelect","mocked","mockFollowCopyJobProgress","createMockDataset","name","aclMode","addonFor","createdAt","createdByUserId","datasetProfile","features","tags","clearAllMocks","pending","pendingMocks","cleanAll","toEqual","stdout","toMatchInlineSnapshot","apiHost","method","uri","reply","id","sourceDataset","state","targetDataset","updatedAt","withHistory","mocks","toContain","query","limit","offset","error","message","oclif","exit","toBe","mockReturnValue","progress","toHaveBeenCalledWith","jobId","Error","mockResolvedValueOnce","choices","arrayContaining","objectContaining","value","each","args","description","expectedError","setupMocks","not","toHaveBeenCalled","mockRejectedValue","desc","flags","flag","undefined"],"mappings":"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"}
|