@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 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/commands/__tests__/init/init.plan.test.ts"],"sourcesContent":["import {mockApi, testCommand} from '@sanity/cli-test'\nimport {afterEach, describe, expect, test, vi} from 'vitest'\n\nimport {InitCommand} from '../../init'\n\nconst mocks = vi.hoisted(() => ({\n confirm: vi.fn(),\n}))\n\nvi.mock('@sanity/cli-core/ux', async () => {\n const actual = await vi.importActual('@sanity/cli-core/ux')\n\n return {\n ...actual,\n confirm: mocks.confirm,\n }\n})\n\nvi.mock('@vercel/fs-detectors', () => ({\n detectFrameworkRecord: vi.fn().mockResolvedValue({\n name: 'Next.js',\n slug: 'nextjs',\n }),\n LocalFileSystemDetector: vi.fn(),\n}))\n\nvi.mock('../../../../../cli-core/src/util/isInteractive.js', () => ({\n isInteractive: vi.fn().mockReturnValue(true),\n}))\n\nvi.mock('../../../../../cli-core/src/services/getCliToken.js', () => ({\n getCliToken: vi.fn().mockResolvedValue('test-token'),\n}))\n\nvi.mock('../../../services/user.js', () => ({\n getCliUser: vi.fn().mockResolvedValue({\n email: 'test@example.com',\n id: 'user-123',\n name: 'Test User',\n provider: 'saml-123',\n }),\n}))\n\ndescribe('#init: retrieving plan', () => {\n afterEach(() => {\n vi.clearAllMocks()\n })\n\n test('validates coupon when --coupon flag is provided', async () => {\n mockApi({\n apiVersion: 'v2025-06-01',\n method: 'get',\n uri: '/plans/coupon/TESTCOUPON123',\n }).reply(200, [{id: 'test-plan-id'}])\n\n const {error, stdout} = await testCommand(InitCommand, ['--coupon=TESTCOUPON123'])\n\n expect(error).toBeUndefined()\n expect(stdout).toContain('Coupon \"TESTCOUPON123\" validated!')\n })\n\n test('throws error if coupon not found with provided code', async () => {\n mockApi({\n apiVersion: 'v2025-06-01',\n method: 'get',\n uri: '/plans/coupon/TESTCOUPON123',\n }).reply(200, [])\n\n const {error} = await testCommand(InitCommand, ['--coupon=TESTCOUPON123', '--bare'])\n\n expect(error?.message).toContain('Unable to validate coupon, please try again later:')\n expect(error?.message).toContain('No plans found for coupon code \"TESTCOUPON123\"')\n })\n\n test('throws error if coupon does not have attached plan id', async () => {\n mockApi({\n apiVersion: 'v2025-06-01',\n method: 'get',\n uri: '/plans/coupon/TESTCOUPON123',\n }).reply(200, [{id: undefined}])\n\n const {error} = await testCommand(InitCommand, ['--coupon=TESTCOUPON123', '--bare'])\n\n expect(error?.message).toContain('Unable to validate coupon, please try again later:')\n expect(error?.message).toContain('Unable to find a plan from coupon code')\n })\n\n test('uses default plan when coupon does not exist and cli in unattended mode', async () => {\n mockApi({\n apiVersion: 'v2025-06-01',\n method: 'get',\n uri: '/plans/coupon/INVALID123',\n }).reply(404, {message: 'Coupon not found'})\n\n const {error, stderr, stdout} = await testCommand(InitCommand, [\n '--coupon=INVALID123',\n '--yes',\n '--dataset=test',\n '--project=test',\n ])\n\n expect(error).toBe(undefined)\n expect(stderr).toContain('Warning: Coupon \"INVALID123\" is not available - using default plan')\n expect(stdout).toContain('Using default plan.')\n })\n\n test('uses default plan when coupon invalid and user confirms default plan', async () => {\n mockApi({\n apiVersion: 'v2025-06-01',\n method: 'get',\n uri: '/plans/coupon/INVALID123',\n }).reply(404, {message: 'Coupon not found'})\n\n mocks.confirm.mockResolvedValue(true)\n\n const {error, stdout} = await testCommand(InitCommand, ['--coupon=INVALID123'])\n\n expect(error).toBeUndefined()\n expect(mocks.confirm).toHaveBeenCalledWith({\n default: true,\n message: 'Coupon \"INVALID123\" is not available, use default plan instead?',\n })\n expect(stdout).toContain('Using default plan.')\n })\n\n test('throws error when coupon invalid and user declines the default plan', async () => {\n mockApi({\n apiVersion: 'v2025-06-01',\n method: 'get',\n uri: '/plans/coupon/INVALID123',\n }).reply(404, {message: 'Coupon not found'})\n mocks.confirm.mockResolvedValue(false)\n\n const {error} = await testCommand(InitCommand, ['--coupon=INVALID123'])\n\n expect(error?.message).toContain('Coupon \"INVALID123\" does not exist')\n })\n\n test('returns when client request for plan is successful', async () => {\n mockApi({\n apiVersion: 'v2025-06-01',\n method: 'get',\n uri: '/plans/growth',\n }).reply(200, [{id: 'test-plan-id'}])\n\n const {error} = await testCommand(InitCommand, ['--project-plan=growth'])\n\n expect(error).toBeUndefined()\n })\n\n test('throw error when no plan id is returned by request', async () => {\n mockApi({\n apiVersion: 'v2025-06-01',\n method: 'get',\n uri: '/plans/growth',\n }).reply(200, [{id: undefined}])\n\n const {error} = await testCommand(InitCommand, ['--project-plan=growth'])\n expect(error?.message).toContain('Unable to validate plan, please try again later:')\n expect(error?.message).toContain('Unable to find a plan with id growth')\n })\n\n test('uses default plan when plan id does not exist and cli in unattended mode', async () => {\n mockApi({\n apiVersion: 'v2025-06-01',\n method: 'get',\n uri: '/plans/growth',\n }).reply(404, {message: 'Plan not found'})\n\n const {error, stderr, stdout} = await testCommand(InitCommand, [\n '--project-plan=growth',\n '--yes',\n '--dataset=test',\n '--project==test',\n ])\n\n expect(error).toBe(undefined)\n expect(stderr).toContain('Warning: Project plan \"growth\" does not exist - using default plan')\n expect(stdout).toContain('Using default plan.')\n })\n\n test('uses default plan when plan ID not found and user confirms default plan', async () => {\n mockApi({\n apiVersion: 'v2025-06-01',\n method: 'get',\n uri: '/plans/growth',\n }).reply(404, {message: 'Plan not found'})\n mocks.confirm.mockResolvedValue(true)\n\n const {error, stdout} = await testCommand(InitCommand, ['--project-plan=growth'])\n\n expect(error).toBeUndefined()\n expect(mocks.confirm).toHaveBeenCalledWith({\n default: true,\n message: 'Project plan \"growth\" does not exist, use default plan instead?',\n })\n expect(stdout).toContain('Using default plan.')\n })\n\n test('throws error when plan ID not found and user declines default plan', async () => {\n mockApi({\n apiVersion: 'v2025-06-01',\n method: 'get',\n uri: '/plans/growth',\n }).reply(404, {message: 'Plan not found'})\n mocks.confirm.mockResolvedValue(false)\n\n const {error} = await testCommand(InitCommand, ['--project-plan=growth'])\n\n expect(error?.message).toContain('Plan id \"growth\" does not exist')\n })\n})\n"],"names":["mockApi","testCommand","afterEach","describe","expect","test","vi","InitCommand","mocks","hoisted","confirm","fn","mock","actual","importActual","detectFrameworkRecord","mockResolvedValue","name","slug","LocalFileSystemDetector","isInteractive","mockReturnValue","getCliToken","getCliUser","email","id","provider","clearAllMocks","apiVersion","method","uri","reply","error","stdout","toBeUndefined","toContain","message","undefined","stderr","toBe","toHaveBeenCalledWith","default"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../src/commands/__tests__/init/init.plan.test.ts"],"sourcesContent":["import {createTestClient, mockApi, testCommand} from '@sanity/cli-test'\nimport {afterEach, describe, expect, test, vi} from 'vitest'\n\nimport {INIT_API_VERSION} from '../../../actions/init/constants.js'\nimport {InitCommand} from '../../init'\n\nconst mockConfirm = vi.hoisted(() => vi.fn())\n\nvi.mock('@sanity/cli-core/ux', async () => {\n const actual = await vi.importActual('@sanity/cli-core/ux')\n\n return {\n ...actual,\n confirm: mockConfirm,\n }\n})\n\nvi.mock('@vercel/fs-detectors', () => ({\n detectFrameworkRecord: vi.fn().mockResolvedValue({\n name: 'Next.js',\n slug: 'nextjs',\n }),\n LocalFileSystemDetector: vi.fn(),\n}))\n\nvi.mock('@sanity/cli-core', async () => {\n const actual = await vi.importActual('@sanity/cli-core')\n const testClient = createTestClient({\n apiVersion: INIT_API_VERSION,\n token: 'test-token',\n })\n\n return {\n ...actual,\n getGlobalCliClient: vi.fn().mockResolvedValue({\n request: testClient.request,\n users: {\n getById: vi.fn().mockResolvedValue({\n email: 'test@example.com',\n id: 'user-123',\n name: 'Test User',\n provider: 'saml-123',\n }),\n } as never,\n }),\n }\n})\n\ndescribe('#init: retrieving plan', () => {\n afterEach(() => {\n vi.clearAllMocks()\n })\n\n test('validates coupon when --coupon flag is provided', async () => {\n mockApi({\n apiVersion: 'v2025-06-01',\n method: 'get',\n uri: '/plans/coupon/TESTCOUPON123',\n }).reply(200, [{id: 'test-plan-id'}])\n\n const {error, stdout} = await testCommand(InitCommand, ['--coupon=TESTCOUPON123'], {\n mocks: {\n isInteractive: true,\n token: 'test-token',\n },\n })\n\n expect(error).toBeUndefined()\n expect(stdout).toContain('Coupon \"TESTCOUPON123\" validated!')\n })\n\n test('throws error if coupon not found with provided code', async () => {\n mockApi({\n apiVersion: 'v2025-06-01',\n method: 'get',\n uri: '/plans/coupon/TESTCOUPON123',\n }).reply(200, [])\n\n const {error} = await testCommand(InitCommand, ['--coupon=TESTCOUPON123', '--bare'], {\n mocks: {\n isInteractive: true,\n token: 'test-token',\n },\n })\n\n expect(error?.message).toContain('Unable to validate coupon, please try again later:')\n expect(error?.message).toContain('No plans found for coupon code \"TESTCOUPON123\"')\n })\n\n test('throws error if coupon does not have attached plan id', async () => {\n mockApi({\n apiVersion: INIT_API_VERSION,\n method: 'get',\n uri: '/plans/coupon/TESTCOUPON123',\n }).reply(200, [{id: undefined}])\n\n const {error} = await testCommand(InitCommand, ['--coupon=TESTCOUPON123', '--bare'], {\n mocks: {\n isInteractive: true,\n token: 'test-token',\n },\n })\n\n expect(error?.message).toContain('Unable to validate coupon, please try again later:')\n expect(error?.message).toContain('Unable to find a plan from coupon code')\n })\n\n test('uses default plan when coupon does not exist and cli in unattended mode', async () => {\n mockApi({\n apiVersion: INIT_API_VERSION,\n method: 'get',\n uri: '/plans/coupon/INVALID123',\n }).reply(404, {message: 'Coupon not found'})\n\n const {error, stderr, stdout} = await testCommand(\n InitCommand,\n ['--coupon=INVALID123', '--yes', '--dataset=test', '--project=test'],\n {\n mocks: {\n token: 'test-token',\n },\n },\n )\n\n expect(error).toBe(undefined)\n expect(stderr).toContain('Warning: Coupon \"INVALID123\" is not available - using default plan')\n expect(stdout).toContain('Using default plan.')\n })\n\n test('uses default plan when coupon invalid and user confirms default plan', async () => {\n mockApi({\n apiVersion: INIT_API_VERSION,\n method: 'get',\n uri: '/plans/coupon/INVALID123',\n }).reply(404, {message: 'Coupon not found'})\n\n mockConfirm.mockResolvedValue(true)\n\n const {error, stdout} = await testCommand(InitCommand, ['--coupon=INVALID123'], {\n mocks: {\n isInteractive: true,\n token: 'test-token',\n },\n })\n\n expect(error).toBeUndefined()\n expect(mockConfirm).toHaveBeenCalledWith({\n default: true,\n message: 'Coupon \"INVALID123\" is not available, use default plan instead?',\n })\n expect(stdout).toContain('Using default plan.')\n })\n\n test('throws error when coupon invalid and user declines the default plan', async () => {\n mockApi({\n apiVersion: INIT_API_VERSION,\n method: 'get',\n uri: '/plans/coupon/INVALID123',\n }).reply(404, {message: 'Coupon not found'})\n mockConfirm.mockResolvedValue(false)\n\n const {error} = await testCommand(InitCommand, ['--coupon=INVALID123'], {\n mocks: {\n isInteractive: true,\n token: 'test-token',\n },\n })\n\n expect(error?.message).toContain('Coupon \"INVALID123\" does not exist')\n })\n\n test('returns when client request for plan is successful', async () => {\n mockApi({\n apiVersion: INIT_API_VERSION,\n method: 'get',\n uri: '/plans/growth',\n }).reply(200, [{id: 'test-plan-id'}])\n\n const {error} = await testCommand(InitCommand, ['--project-plan=growth'], {\n mocks: {\n isInteractive: true,\n token: 'test-token',\n },\n })\n\n expect(error).toBeUndefined()\n })\n\n test('throw error when no plan id is returned by request', async () => {\n mockApi({\n apiVersion: INIT_API_VERSION,\n method: 'get',\n uri: '/plans/growth',\n }).reply(200, [{id: undefined}])\n\n const {error} = await testCommand(InitCommand, ['--project-plan=growth'], {\n mocks: {\n isInteractive: true,\n token: 'test-token',\n },\n })\n expect(error?.message).toContain('Unable to validate plan, please try again later:')\n expect(error?.message).toContain('Unable to find a plan with id growth')\n })\n\n test('uses default plan when plan id does not exist and cli in unattended mode', async () => {\n mockApi({\n apiVersion: INIT_API_VERSION,\n method: 'get',\n uri: '/plans/growth',\n }).reply(404, {message: 'Plan not found'})\n\n const {error, stderr, stdout} = await testCommand(\n InitCommand,\n ['--project-plan=growth', '--yes', '--dataset=test', '--project==test'],\n {\n mocks: {\n token: 'test-token',\n },\n },\n )\n\n expect(error).toBe(undefined)\n expect(stderr).toContain('Warning: Project plan \"growth\" does not exist - using default plan')\n expect(stdout).toContain('Using default plan.')\n })\n\n test('uses default plan when plan ID not found and user confirms default plan', async () => {\n mockApi({\n apiVersion: INIT_API_VERSION,\n method: 'get',\n uri: '/plans/growth',\n }).reply(404, {message: 'Plan not found'})\n mockConfirm.mockResolvedValue(true)\n\n const {error, stdout} = await testCommand(InitCommand, ['--project-plan=growth'], {\n mocks: {\n isInteractive: true,\n token: 'test-token',\n },\n })\n\n expect(error).toBeUndefined()\n expect(mockConfirm).toHaveBeenCalledWith({\n default: true,\n message: 'Project plan \"growth\" does not exist, use default plan instead?',\n })\n expect(stdout).toContain('Using default plan.')\n })\n\n test('throws error when plan ID not found and user declines default plan', async () => {\n mockApi({\n apiVersion: INIT_API_VERSION,\n method: 'get',\n uri: '/plans/growth',\n }).reply(404, {message: 'Plan not found'})\n mockConfirm.mockResolvedValue(false)\n\n const {error} = await testCommand(InitCommand, ['--project-plan=growth'], {\n mocks: {\n isInteractive: true,\n token: 'test-token',\n },\n })\n\n expect(error?.message).toContain('Plan id \"growth\" does not exist')\n })\n})\n"],"names":["createTestClient","mockApi","testCommand","afterEach","describe","expect","test","vi","INIT_API_VERSION","InitCommand","mockConfirm","hoisted","fn","mock","actual","importActual","confirm","detectFrameworkRecord","mockResolvedValue","name","slug","LocalFileSystemDetector","testClient","apiVersion","token","getGlobalCliClient","request","users","getById","email","id","provider","clearAllMocks","method","uri","reply","error","stdout","mocks","isInteractive","toBeUndefined","toContain","message","undefined","stderr","toBe","toHaveBeenCalledWith","default"],"mappings":"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"}
|
|
@@ -5,37 +5,42 @@ import { InitCommand } from '../../init';
|
|
|
5
5
|
const mocks = vi.hoisted(()=>({
|
|
6
6
|
checkIsRemoteTemplate: vi.fn().mockReturnValue(false),
|
|
7
7
|
detectFrameworkRecord: vi.fn(),
|
|
8
|
+
getById: vi.fn(),
|
|
8
9
|
getGitHubRepoInfo: vi.fn()
|
|
9
10
|
}));
|
|
10
11
|
vi.mock('@vercel/fs-detectors', ()=>({
|
|
11
12
|
detectFrameworkRecord: mocks.detectFrameworkRecord,
|
|
12
13
|
LocalFileSystemDetector: vi.fn()
|
|
13
14
|
}));
|
|
14
|
-
vi.mock('../../../../../cli-core/src/util/isInteractive.js', ()=>({
|
|
15
|
-
isInteractive: vi.fn().mockReturnValue(true)
|
|
16
|
-
}));
|
|
17
15
|
vi.mock('../../../actions/init/remoteTemplate.js', ()=>({
|
|
18
16
|
checkIsRemoteTemplate: mocks.checkIsRemoteTemplate,
|
|
19
17
|
getGitHubRepoInfo: mocks.getGitHubRepoInfo
|
|
20
18
|
}));
|
|
21
|
-
vi.mock('
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
provider: 'saml-123'
|
|
19
|
+
vi.mock('@sanity/cli-core', async (importOriginal)=>{
|
|
20
|
+
const actual = await importOriginal();
|
|
21
|
+
return {
|
|
22
|
+
...actual,
|
|
23
|
+
getGlobalCliClient: vi.fn().mockResolvedValue({
|
|
24
|
+
users: {
|
|
25
|
+
getById: mocks.getById
|
|
26
|
+
}
|
|
30
27
|
})
|
|
31
|
-
}
|
|
28
|
+
};
|
|
29
|
+
});
|
|
30
|
+
// Set default mock behavior for getById
|
|
31
|
+
mocks.getById.mockResolvedValue({
|
|
32
|
+
email: 'test@example.com',
|
|
33
|
+
id: 'user-123',
|
|
34
|
+
name: 'Test User',
|
|
35
|
+
provider: 'saml-123'
|
|
36
|
+
});
|
|
32
37
|
describe('#init: oclif command setup', ()=>{
|
|
33
38
|
afterEach(()=>{
|
|
34
39
|
vi.clearAllMocks();
|
|
35
40
|
});
|
|
36
41
|
test('--help works', async ()=>{
|
|
37
42
|
const { stdout } = await runCommand('init --help');
|
|
38
|
-
expect(stdout).toMatchInlineSnapshot(`
|
|
43
|
+
expect(stdout).toMatchInlineSnapshot(String.raw`
|
|
39
44
|
"Initialize a new Sanity Studio, project and/or app
|
|
40
45
|
|
|
41
46
|
USAGE
|
|
@@ -98,19 +103,19 @@ describe('#init: oclif command setup', ()=>{
|
|
|
98
103
|
|
|
99
104
|
Initialize a project with the given project ID and dataset to the given path
|
|
100
105
|
|
|
101
|
-
$ sanity init -y --project abc123 --dataset production --output-path
|
|
106
|
+
$ sanity init -y --project abc123 --dataset production --output-path \
|
|
102
107
|
~/myproj
|
|
103
108
|
|
|
104
109
|
Initialize a project with the given project ID and dataset using the moviedb
|
|
105
110
|
template to the given path
|
|
106
111
|
|
|
107
|
-
$ sanity init -y --project abc123 --dataset staging --template moviedb
|
|
112
|
+
$ sanity init -y --project abc123 --dataset staging --template moviedb \
|
|
108
113
|
--output-path .
|
|
109
114
|
|
|
110
115
|
Create a brand new project with name "Movies Unlimited"
|
|
111
116
|
|
|
112
|
-
$ sanity init -y --create-project "Movies Unlimited" --dataset moviedb
|
|
113
|
-
--visibility private --template moviedb --output-path
|
|
117
|
+
$ sanity init -y --create-project "Movies Unlimited" --dataset moviedb \
|
|
118
|
+
--visibility private --template moviedb --output-path \
|
|
114
119
|
/Users/espenh/movies-unlimited
|
|
115
120
|
|
|
116
121
|
"
|
|
@@ -165,7 +170,12 @@ describe('#init: oclif command setup', ()=>{
|
|
|
165
170
|
const { error } = await testCommand(InitCommand, [
|
|
166
171
|
`--${flag1}`,
|
|
167
172
|
`--${flag2}`
|
|
168
|
-
]
|
|
173
|
+
], {
|
|
174
|
+
mocks: {
|
|
175
|
+
isInteractive: true,
|
|
176
|
+
token: 'test-token'
|
|
177
|
+
}
|
|
178
|
+
});
|
|
169
179
|
const [name1] = flag1.split('=');
|
|
170
180
|
const [name2, value2 = 'true'] = flag2.split('=');
|
|
171
181
|
expect(error?.message).toContain(`--${name2}=${value2} cannot also be provided when using --${name1}`);
|
|
@@ -189,25 +199,45 @@ describe('#init: oclif command setup', ()=>{
|
|
|
189
199
|
])('throws error when `$flag` value is invalid', async ({ flag, message, value })=>{
|
|
190
200
|
const { error } = await testCommand(InitCommand, [
|
|
191
201
|
`--${flag}=${value}`
|
|
192
|
-
]
|
|
202
|
+
], {
|
|
203
|
+
mocks: {
|
|
204
|
+
isInteractive: true,
|
|
205
|
+
token: 'test-token'
|
|
206
|
+
}
|
|
207
|
+
});
|
|
193
208
|
expect(error?.message).toContain(message);
|
|
194
209
|
});
|
|
195
210
|
test('throws error when type argument is passed', async ()=>{
|
|
196
211
|
const { error } = await testCommand(InitCommand, [
|
|
197
212
|
'bad-argument'
|
|
198
|
-
]
|
|
213
|
+
], {
|
|
214
|
+
mocks: {
|
|
215
|
+
isInteractive: true,
|
|
216
|
+
token: 'test-token'
|
|
217
|
+
}
|
|
218
|
+
});
|
|
199
219
|
expect(error?.message).toContain('Unknown init type "bad-argument"');
|
|
200
220
|
});
|
|
201
221
|
test('throws deprecation error when type argument is passed with `plugin`', async ()=>{
|
|
202
222
|
const { error } = await testCommand(InitCommand, [
|
|
203
223
|
'plugin'
|
|
204
|
-
]
|
|
224
|
+
], {
|
|
225
|
+
mocks: {
|
|
226
|
+
isInteractive: true,
|
|
227
|
+
token: 'test-token'
|
|
228
|
+
}
|
|
229
|
+
});
|
|
205
230
|
expect(error?.message).toContain('Initializing plugins through the CLI is no longer supported');
|
|
206
231
|
});
|
|
207
232
|
test('throws error when `reconfigure` flag is passed', async ()=>{
|
|
208
233
|
const { error } = await testCommand(InitCommand, [
|
|
209
234
|
'--reconfigure'
|
|
210
|
-
]
|
|
235
|
+
], {
|
|
236
|
+
mocks: {
|
|
237
|
+
isInteractive: true,
|
|
238
|
+
token: 'test-token'
|
|
239
|
+
}
|
|
240
|
+
});
|
|
211
241
|
expect(error?.message).toContain('--reconfigure is deprecated - manual configuration is now required');
|
|
212
242
|
});
|
|
213
243
|
test('throws error when framework and remote template are used together', async ()=>{
|
|
@@ -223,13 +253,22 @@ describe('#init: oclif command setup', ()=>{
|
|
|
223
253
|
});
|
|
224
254
|
const { error } = await testCommand(InitCommand, [
|
|
225
255
|
'--template=https://github.com/sanity-io/sanity'
|
|
226
|
-
]
|
|
256
|
+
], {
|
|
257
|
+
mocks: {
|
|
258
|
+
isInteractive: true,
|
|
259
|
+
token: 'test-token'
|
|
260
|
+
}
|
|
261
|
+
});
|
|
227
262
|
expect(error?.message).toContain('A remote template cannot be used with a detected framework. Detected: Next.js');
|
|
228
263
|
});
|
|
229
264
|
test('throws error when in unattended mode and `dataset` is not set', async ()=>{
|
|
230
265
|
const { error } = await testCommand(InitCommand, [
|
|
231
266
|
'--yes'
|
|
232
|
-
]
|
|
267
|
+
], {
|
|
268
|
+
mocks: {
|
|
269
|
+
token: 'test-token'
|
|
270
|
+
}
|
|
271
|
+
});
|
|
233
272
|
expect(error?.message).toContain('`--dataset` must be specified in unattended mode');
|
|
234
273
|
});
|
|
235
274
|
test('throws error when `output-path` is not used in unattended mode with non-nextjs project', async ()=>{
|
|
@@ -239,7 +278,11 @@ describe('#init: oclif command setup', ()=>{
|
|
|
239
278
|
'--yes',
|
|
240
279
|
'--dataset=production',
|
|
241
280
|
'--project=test-project'
|
|
242
|
-
]
|
|
281
|
+
], {
|
|
282
|
+
mocks: {
|
|
283
|
+
token: 'test-token'
|
|
284
|
+
}
|
|
285
|
+
});
|
|
243
286
|
// Should throw output-path error for non-Next.js projects
|
|
244
287
|
expect(error?.message).toContain('`--output-path` must be specified in unattended mode');
|
|
245
288
|
});
|
|
@@ -251,7 +294,11 @@ describe('#init: oclif command setup', ()=>{
|
|
|
251
294
|
const { error } = await testCommand(InitCommand, [
|
|
252
295
|
'--yes',
|
|
253
296
|
'--dataset=production'
|
|
254
|
-
]
|
|
297
|
+
], {
|
|
298
|
+
mocks: {
|
|
299
|
+
token: 'test-token'
|
|
300
|
+
}
|
|
301
|
+
});
|
|
255
302
|
expect(error?.message).toContain('`--project <id>` or `--create-project <name>` must be specified in unattended mode');
|
|
256
303
|
});
|
|
257
304
|
test('throws error when in unattended mode and `create-project` not set with `organization`', async ()=>{
|
|
@@ -263,14 +310,23 @@ describe('#init: oclif command setup', ()=>{
|
|
|
263
310
|
'--yes',
|
|
264
311
|
'--dataset=production',
|
|
265
312
|
'--create-project=test'
|
|
266
|
-
]
|
|
313
|
+
], {
|
|
314
|
+
mocks: {
|
|
315
|
+
token: 'test-token'
|
|
316
|
+
}
|
|
317
|
+
});
|
|
267
318
|
expect(error?.message).toContain('--create-project is not supported in unattended mode without an organization, please specify an organization with `--organization <id>`');
|
|
268
319
|
});
|
|
269
320
|
test('logs properly if app template flag is not valid', async ()=>{
|
|
270
321
|
mocks.detectFrameworkRecord.mockResolvedValueOnce(null);
|
|
271
322
|
const { stdout } = await testCommand(InitCommand, [
|
|
272
323
|
'--template=invalid-template-name'
|
|
273
|
-
]
|
|
324
|
+
], {
|
|
325
|
+
mocks: {
|
|
326
|
+
isInteractive: true,
|
|
327
|
+
token: 'test-token'
|
|
328
|
+
}
|
|
329
|
+
});
|
|
274
330
|
// When template is not an app template, it should log "Fetching existing projects"
|
|
275
331
|
expect(stdout).toContain('Fetching existing projects');
|
|
276
332
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/commands/__tests__/init/init.setup.test.ts"],"sourcesContent":["import {runCommand} from '@oclif/test'\nimport {testCommand} from '@sanity/cli-test'\nimport {afterEach, describe, expect, test, vi} from 'vitest'\n\nimport {InitCommand} from '../../init'\n\nconst mocks = vi.hoisted(() => ({\n checkIsRemoteTemplate: vi.fn().mockReturnValue(false),\n detectFrameworkRecord: vi.fn(),\n getGitHubRepoInfo: vi.fn(),\n}))\n\nvi.mock('@vercel/fs-detectors', () => ({\n detectFrameworkRecord: mocks.detectFrameworkRecord,\n LocalFileSystemDetector: vi.fn(),\n}))\n\nvi.mock('../../../../../cli-core/src/util/isInteractive.js', () => ({\n isInteractive: vi.fn().mockReturnValue(true),\n}))\n\nvi.mock('../../../actions/init/remoteTemplate.js', () => ({\n checkIsRemoteTemplate: mocks.checkIsRemoteTemplate,\n getGitHubRepoInfo: mocks.getGitHubRepoInfo,\n}))\n\nvi.mock('../../../../../cli-core/src/services/getCliToken.js', () => ({\n getCliToken: vi.fn().mockResolvedValue('test-token'),\n}))\n\nvi.mock('../../../services/user.js', () => ({\n getCliUser: vi.fn().mockResolvedValue({\n email: 'test@example.com',\n id: 'user-123',\n name: 'Test User',\n provider: 'saml-123',\n }),\n}))\n\ndescribe('#init: oclif command setup', () => {\n afterEach(() => {\n vi.clearAllMocks()\n })\n\n test('--help works', async () => {\n const {stdout} = await runCommand('init --help')\n\n expect(stdout).toMatchInlineSnapshot(`\n \"Initialize a new Sanity Studio, project and/or app\n\n USAGE\n $ sanity init [--json] [--auto-updates | --bare] [--coupon\n <code> | --project-plan <name>] [--dataset <name> | --dataset-default]\n [--env <filename> | ] [--git <message> | ] [--mcp]\n [--nextjs-add-config-files] [--nextjs-append-env] [--nextjs-embed-studio]\n [--organization <id>] [--output-path <path> | ] [--overwrite-files]\n [--package-manager <manager> | ] [--project <id> | --create-project <name>]\n [--provider <provider>] [--template <template> | ] [--typescript | ]\n [--visibility <mode>] [-y]\n\n FLAGS\n -y, --yes Unattended mode, answers \"yes\" to any\n \"yes/no\" prompt and otherwise uses defaults\n --[no-]auto-updates Enable auto updates of studio versions\n --bare Skip the Studio initialization and only print\n the selected project ID and dataset name to\n stdout\n --coupon=<code> Optionally select a coupon for a new project\n (cannot be used with --project-plan)\n --create-project=<name> Create a new project with the given name\n --dataset=<name> Dataset name for the studio\n --dataset-default Set up a project with a public dataset named\n \"production\"\n --env=<filename> Write environment variables to file\n --[no-]git=<message> Specify a commit message for initial commit,\n or disable git init\n --[no-]mcp Enable AI editor integration (MCP) setup\n --organization=<id> Organization ID to use for the project\n --output-path=<path> Path to write studio project to\n --overwrite-files Overwrite existing files\n --package-manager=<manager> Specify which package manager to use\n [allowed: npm, yarn, pnpm]\n --project=<id> Project ID to use for the studio\n --project-plan=<name> Optionally select a plan for a new project\n --provider=<provider> Login provider to use\n --template=<template> [default: clean] Project template to use\n [default: \"clean\"]\n --[no-]typescript Enable TypeScript support\n --visibility=<mode> Visibility mode for dataset\n\n GLOBAL FLAGS\n --json Format output as json.\n\n NEXT.JS FLAGS\n --[no-]nextjs-add-config-files Add config files to Next.js project\n --[no-]nextjs-append-env Append project ID and dataset to .env file\n --[no-]nextjs-embed-studio Embed the Studio in Next.js application\n\n DESCRIPTION\n Initialize a new Sanity Studio, project and/or app\n\n EXAMPLES\n $ sanity init\n\n Initialize a new project with a public dataset named \"production\"\n\n $ sanity init --dataset-default\n\n Initialize a project with the given project ID and dataset to the given path\n\n $ sanity init -y --project abc123 --dataset production --output-path \\\\\n ~/myproj\n\n Initialize a project with the given project ID and dataset using the moviedb\n template to the given path\n\n $ sanity init -y --project abc123 --dataset staging --template moviedb \\\\\n --output-path .\n\n Create a brand new project with name \"Movies Unlimited\"\n\n $ sanity init -y --create-project \"Movies Unlimited\" --dataset moviedb \\\\\n --visibility private --template moviedb --output-path \\\\\n /Users/espenh/movies-unlimited\n\n \"\n `)\n })\n\n test.each([\n {flag1: 'auto-updates', flag2: 'bare'},\n {flag1: 'coupon=123', flag2: 'project-plan=123'},\n {flag1: 'dataset=\"123', flag2: 'dataset-default'},\n {flag1: 'env=.env', flag2: 'bare'},\n {flag1: 'git=test', flag2: 'bare'},\n {flag1: 'no-git', flag2: 'git=test'},\n {flag1: 'output-path=/test-path', flag2: 'bare'},\n {flag1: 'package-manager=pnpm', flag2: 'bare'},\n {flag1: 'template=test', flag2: 'bare'},\n {flag1: 'typescript', flag2: 'bare'},\n {flag1: 'project=test', flag2: 'create-project=test'},\n ])('throws error when `$flag1` and `$flag2` flags are both passed', async ({flag1, flag2}) => {\n const {error} = await testCommand(InitCommand, [`--${flag1}`, `--${flag2}`])\n\n const [name1] = flag1.split('=')\n const [name2, value2 = 'true'] = flag2.split('=')\n\n expect(error?.message).toContain(\n `--${name2}=${value2} cannot also be provided when using --${name1}`,\n )\n })\n\n test.each([\n {flag: 'env', message: 'Env filename (`--env`) must start with `.env`', value: 'invalid.txt'},\n {\n flag: 'visibility',\n message: 'Expected --visibility=opaque to be one of: public, private',\n value: 'opaque',\n },\n {\n flag: 'package-manager',\n message: 'Expected --package-manager=pnm to be one of: npm, yarn, pnpm',\n value: 'pnm',\n },\n ])('throws error when `$flag` value is invalid', async ({flag, message, value}) => {\n const {error} = await testCommand(InitCommand, [`--${flag}=${value}`])\n\n expect(error?.message).toContain(message)\n })\n\n test('throws error when type argument is passed', async () => {\n const {error} = await testCommand(InitCommand, ['bad-argument'])\n\n expect(error?.message).toContain('Unknown init type \"bad-argument\"')\n })\n\n test('throws deprecation error when type argument is passed with `plugin`', async () => {\n const {error} = await testCommand(InitCommand, ['plugin'])\n\n expect(error?.message).toContain('Initializing plugins through the CLI is no longer supported')\n })\n\n test('throws error when `reconfigure` flag is passed', async () => {\n const {error} = await testCommand(InitCommand, ['--reconfigure'])\n\n expect(error?.message).toContain(\n '--reconfigure is deprecated - manual configuration is now required',\n )\n })\n\n test('throws error when framework and remote template are used together', async () => {\n mocks.detectFrameworkRecord.mockResolvedValueOnce({\n name: 'Next.js',\n slug: 'nextjs',\n })\n mocks.checkIsRemoteTemplate.mockReturnValueOnce(true)\n mocks.getGitHubRepoInfo.mockResolvedValueOnce({\n branch: 'main',\n owner: 'sanity-io',\n repo: 'sanity',\n })\n\n const {error} = await testCommand(InitCommand, [\n '--template=https://github.com/sanity-io/sanity',\n ])\n\n expect(error?.message).toContain(\n 'A remote template cannot be used with a detected framework. Detected: Next.js',\n )\n })\n\n test('throws error when in unattended mode and `dataset` is not set', async () => {\n const {error} = await testCommand(InitCommand, ['--yes'])\n\n expect(error?.message).toContain('`--dataset` must be specified in unattended mode')\n })\n\n test('throws error when `output-path` is not used in unattended mode with non-nextjs project', async () => {\n // Mock no framework or a non-Next.js framework\n mocks.detectFrameworkRecord.mockResolvedValueOnce(null)\n\n const {error} = await testCommand(InitCommand, [\n '--yes',\n '--dataset=production',\n '--project=test-project',\n ])\n\n // Should throw output-path error for non-Next.js projects\n expect(error?.message).toContain('`--output-path` must be specified in unattended mode')\n })\n\n test('throws error when in unattended mode and `project` and `create-project` not set', async () => {\n mocks.detectFrameworkRecord.mockResolvedValueOnce({\n name: 'Next.js',\n slug: 'nextjs',\n })\n\n const {error} = await testCommand(InitCommand, [\n '--yes',\n '--dataset=production',\n // Deliberately omitting --project and --create-project\n ])\n\n expect(error?.message).toContain(\n '`--project <id>` or `--create-project <name>` must be specified in unattended mode',\n )\n })\n\n test('throws error when in unattended mode and `create-project` not set with `organization`', async () => {\n mocks.detectFrameworkRecord.mockResolvedValueOnce({\n name: 'Next.js',\n slug: 'nextjs',\n })\n\n const {error} = await testCommand(InitCommand, [\n '--yes',\n '--dataset=production',\n '--create-project=test',\n ])\n\n expect(error?.message).toContain(\n '--create-project is not supported in unattended mode without an organization, please specify an organization with `--organization <id>`',\n )\n })\n\n test('logs properly if app template flag is not valid', async () => {\n mocks.detectFrameworkRecord.mockResolvedValueOnce(null)\n\n const {stdout} = await testCommand(InitCommand, [\n '--template=invalid-template-name', // Not a valid app template\n ])\n\n // When template is not an app template, it should log \"Fetching existing projects\"\n expect(stdout).toContain('Fetching existing projects')\n })\n})\n"],"names":["runCommand","testCommand","afterEach","describe","expect","test","vi","InitCommand","mocks","hoisted","checkIsRemoteTemplate","fn","mockReturnValue","detectFrameworkRecord","getGitHubRepoInfo","mock","LocalFileSystemDetector","isInteractive","getCliToken","mockResolvedValue","getCliUser","email","id","name","provider","clearAllMocks","stdout","toMatchInlineSnapshot","each","flag1","flag2","error","name1","split","name2","value2","message","toContain","flag","value","mockResolvedValueOnce","slug","mockReturnValueOnce","branch","owner","repo"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../src/commands/__tests__/init/init.setup.test.ts"],"sourcesContent":["import {runCommand} from '@oclif/test'\nimport {testCommand} from '@sanity/cli-test'\nimport {afterEach, describe, expect, test, vi} from 'vitest'\n\nimport {InitCommand} from '../../init'\n\nconst mocks = vi.hoisted(() => ({\n checkIsRemoteTemplate: vi.fn().mockReturnValue(false),\n detectFrameworkRecord: vi.fn(),\n getById: vi.fn(),\n getGitHubRepoInfo: vi.fn(),\n}))\n\nvi.mock('@vercel/fs-detectors', () => ({\n detectFrameworkRecord: mocks.detectFrameworkRecord,\n LocalFileSystemDetector: vi.fn(),\n}))\n\nvi.mock('../../../actions/init/remoteTemplate.js', () => ({\n checkIsRemoteTemplate: mocks.checkIsRemoteTemplate,\n getGitHubRepoInfo: mocks.getGitHubRepoInfo,\n}))\n\nvi.mock('@sanity/cli-core', async (importOriginal) => {\n const actual = await importOriginal<typeof import('@sanity/cli-core')>()\n return {\n ...actual,\n getGlobalCliClient: vi.fn().mockResolvedValue({\n users: {\n getById: mocks.getById,\n } as never,\n }),\n }\n})\n\n// Set default mock behavior for getById\nmocks.getById.mockResolvedValue({\n email: 'test@example.com',\n id: 'user-123',\n name: 'Test User',\n provider: 'saml-123',\n})\n\ndescribe('#init: oclif command setup', () => {\n afterEach(() => {\n vi.clearAllMocks()\n })\n\n test('--help works', async () => {\n const {stdout} = await runCommand('init --help')\n\n expect(stdout).toMatchInlineSnapshot(String.raw`\n \"Initialize a new Sanity Studio, project and/or app\n\n USAGE\n $ sanity init [--json] [--auto-updates | --bare] [--coupon\n <code> | --project-plan <name>] [--dataset <name> | --dataset-default]\n [--env <filename> | ] [--git <message> | ] [--mcp]\n [--nextjs-add-config-files] [--nextjs-append-env] [--nextjs-embed-studio]\n [--organization <id>] [--output-path <path> | ] [--overwrite-files]\n [--package-manager <manager> | ] [--project <id> | --create-project <name>]\n [--provider <provider>] [--template <template> | ] [--typescript | ]\n [--visibility <mode>] [-y]\n\n FLAGS\n -y, --yes Unattended mode, answers \"yes\" to any\n \"yes/no\" prompt and otherwise uses defaults\n --[no-]auto-updates Enable auto updates of studio versions\n --bare Skip the Studio initialization and only print\n the selected project ID and dataset name to\n stdout\n --coupon=<code> Optionally select a coupon for a new project\n (cannot be used with --project-plan)\n --create-project=<name> Create a new project with the given name\n --dataset=<name> Dataset name for the studio\n --dataset-default Set up a project with a public dataset named\n \"production\"\n --env=<filename> Write environment variables to file\n --[no-]git=<message> Specify a commit message for initial commit,\n or disable git init\n --[no-]mcp Enable AI editor integration (MCP) setup\n --organization=<id> Organization ID to use for the project\n --output-path=<path> Path to write studio project to\n --overwrite-files Overwrite existing files\n --package-manager=<manager> Specify which package manager to use\n [allowed: npm, yarn, pnpm]\n --project=<id> Project ID to use for the studio\n --project-plan=<name> Optionally select a plan for a new project\n --provider=<provider> Login provider to use\n --template=<template> [default: clean] Project template to use\n [default: \"clean\"]\n --[no-]typescript Enable TypeScript support\n --visibility=<mode> Visibility mode for dataset\n\n GLOBAL FLAGS\n --json Format output as json.\n\n NEXT.JS FLAGS\n --[no-]nextjs-add-config-files Add config files to Next.js project\n --[no-]nextjs-append-env Append project ID and dataset to .env file\n --[no-]nextjs-embed-studio Embed the Studio in Next.js application\n\n DESCRIPTION\n Initialize a new Sanity Studio, project and/or app\n\n EXAMPLES\n $ sanity init\n\n Initialize a new project with a public dataset named \"production\"\n\n $ sanity init --dataset-default\n\n Initialize a project with the given project ID and dataset to the given path\n\n $ sanity init -y --project abc123 --dataset production --output-path \\\n ~/myproj\n\n Initialize a project with the given project ID and dataset using the moviedb\n template to the given path\n\n $ sanity init -y --project abc123 --dataset staging --template moviedb \\\n --output-path .\n\n Create a brand new project with name \"Movies Unlimited\"\n\n $ sanity init -y --create-project \"Movies Unlimited\" --dataset moviedb \\\n --visibility private --template moviedb --output-path \\\n /Users/espenh/movies-unlimited\n\n \"\n `)\n })\n\n test.each([\n {flag1: 'auto-updates', flag2: 'bare'},\n {flag1: 'coupon=123', flag2: 'project-plan=123'},\n {flag1: 'dataset=\"123', flag2: 'dataset-default'},\n {flag1: 'env=.env', flag2: 'bare'},\n {flag1: 'git=test', flag2: 'bare'},\n {flag1: 'no-git', flag2: 'git=test'},\n {flag1: 'output-path=/test-path', flag2: 'bare'},\n {flag1: 'package-manager=pnpm', flag2: 'bare'},\n {flag1: 'template=test', flag2: 'bare'},\n {flag1: 'typescript', flag2: 'bare'},\n {flag1: 'project=test', flag2: 'create-project=test'},\n ])('throws error when `$flag1` and `$flag2` flags are both passed', async ({flag1, flag2}) => {\n const {error} = await testCommand(InitCommand, [`--${flag1}`, `--${flag2}`], {\n mocks: {\n isInteractive: true,\n token: 'test-token',\n },\n })\n\n const [name1] = flag1.split('=')\n const [name2, value2 = 'true'] = flag2.split('=')\n\n expect(error?.message).toContain(\n `--${name2}=${value2} cannot also be provided when using --${name1}`,\n )\n })\n\n test.each([\n {flag: 'env', message: 'Env filename (`--env`) must start with `.env`', value: 'invalid.txt'},\n {\n flag: 'visibility',\n message: 'Expected --visibility=opaque to be one of: public, private',\n value: 'opaque',\n },\n {\n flag: 'package-manager',\n message: 'Expected --package-manager=pnm to be one of: npm, yarn, pnpm',\n value: 'pnm',\n },\n ])('throws error when `$flag` value is invalid', async ({flag, message, value}) => {\n const {error} = await testCommand(InitCommand, [`--${flag}=${value}`], {\n mocks: {\n isInteractive: true,\n token: 'test-token',\n },\n })\n\n expect(error?.message).toContain(message)\n })\n\n test('throws error when type argument is passed', async () => {\n const {error} = await testCommand(InitCommand, ['bad-argument'], {\n mocks: {\n isInteractive: true,\n token: 'test-token',\n },\n })\n\n expect(error?.message).toContain('Unknown init type \"bad-argument\"')\n })\n\n test('throws deprecation error when type argument is passed with `plugin`', async () => {\n const {error} = await testCommand(InitCommand, ['plugin'], {\n mocks: {\n isInteractive: true,\n token: 'test-token',\n },\n })\n\n expect(error?.message).toContain('Initializing plugins through the CLI is no longer supported')\n })\n\n test('throws error when `reconfigure` flag is passed', async () => {\n const {error} = await testCommand(InitCommand, ['--reconfigure'], {\n mocks: {\n isInteractive: true,\n token: 'test-token',\n },\n })\n\n expect(error?.message).toContain(\n '--reconfigure is deprecated - manual configuration is now required',\n )\n })\n\n test('throws error when framework and remote template are used together', async () => {\n mocks.detectFrameworkRecord.mockResolvedValueOnce({\n name: 'Next.js',\n slug: 'nextjs',\n })\n mocks.checkIsRemoteTemplate.mockReturnValueOnce(true)\n mocks.getGitHubRepoInfo.mockResolvedValueOnce({\n branch: 'main',\n owner: 'sanity-io',\n repo: 'sanity',\n })\n\n const {error} = await testCommand(\n InitCommand,\n ['--template=https://github.com/sanity-io/sanity'],\n {\n mocks: {\n isInteractive: true,\n token: 'test-token',\n },\n },\n )\n\n expect(error?.message).toContain(\n 'A remote template cannot be used with a detected framework. Detected: Next.js',\n )\n })\n\n test('throws error when in unattended mode and `dataset` is not set', async () => {\n const {error} = await testCommand(InitCommand, ['--yes'], {\n mocks: {\n token: 'test-token',\n },\n })\n\n expect(error?.message).toContain('`--dataset` must be specified in unattended mode')\n })\n\n test('throws error when `output-path` is not used in unattended mode with non-nextjs project', async () => {\n // Mock no framework or a non-Next.js framework\n mocks.detectFrameworkRecord.mockResolvedValueOnce(null)\n\n const {error} = await testCommand(\n InitCommand,\n ['--yes', '--dataset=production', '--project=test-project'],\n {\n mocks: {\n token: 'test-token',\n },\n },\n )\n\n // Should throw output-path error for non-Next.js projects\n expect(error?.message).toContain('`--output-path` must be specified in unattended mode')\n })\n\n test('throws error when in unattended mode and `project` and `create-project` not set', async () => {\n mocks.detectFrameworkRecord.mockResolvedValueOnce({\n name: 'Next.js',\n slug: 'nextjs',\n })\n\n const {error} = await testCommand(\n InitCommand,\n [\n '--yes',\n '--dataset=production',\n // Deliberately omitting --project and --create-project\n ],\n {\n mocks: {\n token: 'test-token',\n },\n },\n )\n\n expect(error?.message).toContain(\n '`--project <id>` or `--create-project <name>` must be specified in unattended mode',\n )\n })\n\n test('throws error when in unattended mode and `create-project` not set with `organization`', async () => {\n mocks.detectFrameworkRecord.mockResolvedValueOnce({\n name: 'Next.js',\n slug: 'nextjs',\n })\n\n const {error} = await testCommand(\n InitCommand,\n ['--yes', '--dataset=production', '--create-project=test'],\n {\n mocks: {\n token: 'test-token',\n },\n },\n )\n\n expect(error?.message).toContain(\n '--create-project is not supported in unattended mode without an organization, please specify an organization with `--organization <id>`',\n )\n })\n\n test('logs properly if app template flag is not valid', async () => {\n mocks.detectFrameworkRecord.mockResolvedValueOnce(null)\n\n const {stdout} = await testCommand(\n InitCommand,\n [\n '--template=invalid-template-name', // Not a valid app template\n ],\n {\n mocks: {\n isInteractive: true,\n token: 'test-token',\n },\n },\n )\n\n // When template is not an app template, it should log \"Fetching existing projects\"\n expect(stdout).toContain('Fetching existing projects')\n })\n})\n"],"names":["runCommand","testCommand","afterEach","describe","expect","test","vi","InitCommand","mocks","hoisted","checkIsRemoteTemplate","fn","mockReturnValue","detectFrameworkRecord","getById","getGitHubRepoInfo","mock","LocalFileSystemDetector","importOriginal","actual","getGlobalCliClient","mockResolvedValue","users","email","id","name","provider","clearAllMocks","stdout","toMatchInlineSnapshot","String","raw","each","flag1","flag2","error","isInteractive","token","name1","split","name2","value2","message","toContain","flag","value","mockResolvedValueOnce","slug","mockReturnValueOnce","branch","owner","repo"],"mappings":"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"}
|
|
@@ -4,15 +4,6 @@ import { afterEach, describe, expect, test, vi } from 'vitest';
|
|
|
4
4
|
import { installDeclaredPackages, installNewPackages } from '../../util/packageManager/installPackages.js';
|
|
5
5
|
import { getPackageManagerChoice } from '../../util/packageManager/packageManagerChoice.js';
|
|
6
6
|
import { Install } from '../install.js';
|
|
7
|
-
vi.mock('../../../../cli-core/src/config/findProjectRoot.js', async ()=>{
|
|
8
|
-
return {
|
|
9
|
-
findProjectRoot: vi.fn().mockResolvedValue({
|
|
10
|
-
directory: '/test/project',
|
|
11
|
-
root: '/test/project',
|
|
12
|
-
type: 'studio'
|
|
13
|
-
})
|
|
14
|
-
};
|
|
15
|
-
});
|
|
16
7
|
vi.mock('../../util/packageManager/packageManagerChoice.js', ()=>({
|
|
17
8
|
getPackageManagerChoice: vi.fn()
|
|
18
9
|
}));
|
|
@@ -23,6 +14,13 @@ vi.mock('../../util/packageManager/installPackages.js', ()=>({
|
|
|
23
14
|
const mockGetPackageManagerChoice = vi.mocked(getPackageManagerChoice);
|
|
24
15
|
const mockInstallDeclaredPackages = vi.mocked(installDeclaredPackages);
|
|
25
16
|
const mockInstallNewPackages = vi.mocked(installNewPackages);
|
|
17
|
+
const defaultMocks = {
|
|
18
|
+
projectRoot: {
|
|
19
|
+
directory: '/test/project',
|
|
20
|
+
path: '/test/project/sanity.config.ts',
|
|
21
|
+
type: 'studio'
|
|
22
|
+
}
|
|
23
|
+
};
|
|
26
24
|
afterEach(()=>{
|
|
27
25
|
vi.clearAllMocks();
|
|
28
26
|
});
|
|
@@ -58,7 +56,9 @@ describe('#install', ()=>{
|
|
|
58
56
|
mostOptimal: 'npm'
|
|
59
57
|
});
|
|
60
58
|
mockInstallDeclaredPackages.mockResolvedValueOnce();
|
|
61
|
-
const { error } = await testCommand(Install, []
|
|
59
|
+
const { error } = await testCommand(Install, [], {
|
|
60
|
+
mocks: defaultMocks
|
|
61
|
+
});
|
|
62
62
|
expect(error).toBeUndefined();
|
|
63
63
|
expect(mockGetPackageManagerChoice).toHaveBeenCalledWith('/test/project', {
|
|
64
64
|
interactive: true
|
|
@@ -74,7 +74,9 @@ describe('#install', ()=>{
|
|
|
74
74
|
mostOptimal: 'yarn'
|
|
75
75
|
});
|
|
76
76
|
mockInstallDeclaredPackages.mockResolvedValueOnce();
|
|
77
|
-
const { error } = await testCommand(Install, []
|
|
77
|
+
const { error } = await testCommand(Install, [], {
|
|
78
|
+
mocks: defaultMocks
|
|
79
|
+
});
|
|
78
80
|
expect(error).toBeUndefined();
|
|
79
81
|
expect(mockInstallDeclaredPackages).toHaveBeenCalledWith('/test/project', 'yarn', expect.objectContaining({
|
|
80
82
|
workDir: '/test/project'
|
|
@@ -86,7 +88,9 @@ describe('#install', ()=>{
|
|
|
86
88
|
mostOptimal: 'pnpm'
|
|
87
89
|
});
|
|
88
90
|
mockInstallDeclaredPackages.mockResolvedValueOnce();
|
|
89
|
-
const { error } = await testCommand(Install, []
|
|
91
|
+
const { error } = await testCommand(Install, [], {
|
|
92
|
+
mocks: defaultMocks
|
|
93
|
+
});
|
|
90
94
|
expect(error).toBeUndefined();
|
|
91
95
|
expect(mockInstallDeclaredPackages).toHaveBeenCalledWith('/test/project', 'pnpm', expect.objectContaining({
|
|
92
96
|
workDir: '/test/project'
|
|
@@ -98,7 +102,9 @@ describe('#install', ()=>{
|
|
|
98
102
|
mostOptimal: 'bun'
|
|
99
103
|
});
|
|
100
104
|
mockInstallDeclaredPackages.mockResolvedValueOnce();
|
|
101
|
-
const { error } = await testCommand(Install, []
|
|
105
|
+
const { error } = await testCommand(Install, [], {
|
|
106
|
+
mocks: defaultMocks
|
|
107
|
+
});
|
|
102
108
|
expect(error).toBeUndefined();
|
|
103
109
|
expect(mockInstallDeclaredPackages).toHaveBeenCalledWith('/test/project', 'bun', expect.objectContaining({
|
|
104
110
|
workDir: '/test/project'
|
|
@@ -110,7 +116,9 @@ describe('#install', ()=>{
|
|
|
110
116
|
mostOptimal: 'npm'
|
|
111
117
|
});
|
|
112
118
|
mockInstallDeclaredPackages.mockResolvedValueOnce();
|
|
113
|
-
const { error } = await testCommand(Install, []
|
|
119
|
+
const { error } = await testCommand(Install, [], {
|
|
120
|
+
mocks: defaultMocks
|
|
121
|
+
});
|
|
114
122
|
expect(error).toBeUndefined();
|
|
115
123
|
expect(mockInstallDeclaredPackages).toHaveBeenCalledWith('/test/project', 'manual', expect.objectContaining({
|
|
116
124
|
workDir: '/test/project'
|
|
@@ -126,7 +134,9 @@ describe('#install', ()=>{
|
|
|
126
134
|
mockInstallNewPackages.mockResolvedValueOnce();
|
|
127
135
|
const { error } = await testCommand(Install, [
|
|
128
136
|
'@sanity/vision'
|
|
129
|
-
]
|
|
137
|
+
], {
|
|
138
|
+
mocks: defaultMocks
|
|
139
|
+
});
|
|
130
140
|
expect(error).toBeUndefined();
|
|
131
141
|
expect(mockInstallNewPackages).toHaveBeenCalledWith({
|
|
132
142
|
packageManager: 'npm',
|
|
@@ -148,7 +158,9 @@ describe('#install', ()=>{
|
|
|
148
158
|
'@sanity/vision',
|
|
149
159
|
'react-icons',
|
|
150
160
|
'lodash'
|
|
151
|
-
]
|
|
161
|
+
], {
|
|
162
|
+
mocks: defaultMocks
|
|
163
|
+
});
|
|
152
164
|
expect(error).toBeUndefined();
|
|
153
165
|
expect(mockInstallNewPackages).toHaveBeenCalledWith({
|
|
154
166
|
packageManager: 'yarn',
|
|
@@ -170,7 +182,9 @@ describe('#install', ()=>{
|
|
|
170
182
|
mockInstallNewPackages.mockResolvedValueOnce();
|
|
171
183
|
const { error } = await testCommand(Install, [
|
|
172
184
|
'some-package'
|
|
173
|
-
]
|
|
185
|
+
], {
|
|
186
|
+
mocks: defaultMocks
|
|
187
|
+
});
|
|
174
188
|
expect(error).toBeUndefined();
|
|
175
189
|
expect(mockInstallNewPackages).toHaveBeenCalledWith({
|
|
176
190
|
packageManager: 'pnpm',
|
|
@@ -185,7 +199,9 @@ describe('#install', ()=>{
|
|
|
185
199
|
describe('error handling', ()=>{
|
|
186
200
|
test('handles package manager choice failure', async ()=>{
|
|
187
201
|
mockGetPackageManagerChoice.mockRejectedValueOnce(new Error('Failed to detect package manager'));
|
|
188
|
-
const { error } = await testCommand(Install, []
|
|
202
|
+
const { error } = await testCommand(Install, [], {
|
|
203
|
+
mocks: defaultMocks
|
|
204
|
+
});
|
|
189
205
|
expect(error).toBeDefined();
|
|
190
206
|
expect(error?.message).toContain('Failed to detect package manager');
|
|
191
207
|
expect(mockInstallDeclaredPackages).not.toHaveBeenCalled();
|
|
@@ -197,7 +213,9 @@ describe('#install', ()=>{
|
|
|
197
213
|
mostOptimal: 'npm'
|
|
198
214
|
});
|
|
199
215
|
mockInstallDeclaredPackages.mockRejectedValueOnce(new Error('Installation failed'));
|
|
200
|
-
const { error } = await testCommand(Install, []
|
|
216
|
+
const { error } = await testCommand(Install, [], {
|
|
217
|
+
mocks: defaultMocks
|
|
218
|
+
});
|
|
201
219
|
expect(error).toBeDefined();
|
|
202
220
|
expect(error?.message).toContain('Installation failed');
|
|
203
221
|
});
|
|
@@ -209,7 +227,9 @@ describe('#install', ()=>{
|
|
|
209
227
|
mockInstallNewPackages.mockRejectedValueOnce(new Error('Package not found'));
|
|
210
228
|
const { error } = await testCommand(Install, [
|
|
211
229
|
'nonexistent-package'
|
|
212
|
-
]
|
|
230
|
+
], {
|
|
231
|
+
mocks: defaultMocks
|
|
232
|
+
});
|
|
213
233
|
expect(error).toBeDefined();
|
|
214
234
|
expect(error?.message).toContain('Package not found');
|
|
215
235
|
});
|
|
@@ -221,7 +241,9 @@ describe('#install', ()=>{
|
|
|
221
241
|
mostOptimal: 'npm'
|
|
222
242
|
});
|
|
223
243
|
mockInstallDeclaredPackages.mockResolvedValueOnce();
|
|
224
|
-
await testCommand(Install, []
|
|
244
|
+
await testCommand(Install, [], {
|
|
245
|
+
mocks: defaultMocks
|
|
246
|
+
});
|
|
225
247
|
expect(mockGetPackageManagerChoice).toHaveBeenCalledWith('/test/project', {
|
|
226
248
|
interactive: true
|
|
227
249
|
});
|
|
@@ -237,7 +259,9 @@ describe('#install', ()=>{
|
|
|
237
259
|
mockInstallNewPackages.mockResolvedValueOnce();
|
|
238
260
|
await testCommand(Install, [
|
|
239
261
|
'test-package'
|
|
240
|
-
]
|
|
262
|
+
], {
|
|
263
|
+
mocks: defaultMocks
|
|
264
|
+
});
|
|
241
265
|
expect(mockInstallNewPackages).toHaveBeenCalledWith({
|
|
242
266
|
packageManager: 'npm',
|
|
243
267
|
packages: [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/commands/__tests__/install.test.ts"],"sourcesContent":["import {runCommand} from '@oclif/test'\nimport {testCommand} from '@sanity/cli-test'\nimport {afterEach, describe, expect, test, vi} from 'vitest'\n\nimport {\n installDeclaredPackages,\n installNewPackages,\n} from '../../util/packageManager/installPackages.js'\nimport {getPackageManagerChoice} from '../../util/packageManager/packageManagerChoice.js'\nimport {Install} from '../install.js'\n\nvi.mock('../../../../cli-core/src/config/findProjectRoot.js', async () => {\n return {\n findProjectRoot: vi.fn().mockResolvedValue({\n directory: '/test/project',\n root: '/test/project',\n type: 'studio',\n }),\n }\n})\n\nvi.mock('../../util/packageManager/packageManagerChoice.js', () => ({\n getPackageManagerChoice: vi.fn(),\n}))\n\nvi.mock('../../util/packageManager/installPackages.js', () => ({\n installDeclaredPackages: vi.fn(),\n installNewPackages: vi.fn(),\n}))\n\nconst mockGetPackageManagerChoice = vi.mocked(getPackageManagerChoice)\nconst mockInstallDeclaredPackages = vi.mocked(installDeclaredPackages)\nconst mockInstallNewPackages = vi.mocked(installNewPackages)\n\nafterEach(() => {\n vi.clearAllMocks()\n})\n\ndescribe('#install', () => {\n test('help text is correct', async () => {\n const {stdout} = await runCommand('install --help')\n expect(stdout).toMatchInlineSnapshot(`\n \"Installs dependencies for Sanity Studio project\n\n USAGE\n $ sanity install [PACKAGES...]\n\n ARGUMENTS\n [PACKAGES...] Packages to install\n\n DESCRIPTION\n Installs dependencies for Sanity Studio project\n\n EXAMPLES\n $ sanity install\n\n $ sanity install @sanity/vision\n\n $ sanity install some-package another-package\n\n \"\n `)\n })\n\n describe('install declared packages (no arguments)', () => {\n test('installs declared packages with npm', async () => {\n mockGetPackageManagerChoice.mockResolvedValueOnce({\n chosen: 'npm',\n mostOptimal: 'npm',\n })\n mockInstallDeclaredPackages.mockResolvedValueOnce()\n\n const {error} = await testCommand(Install, [])\n\n expect(error).toBeUndefined()\n expect(mockGetPackageManagerChoice).toHaveBeenCalledWith('/test/project', {\n interactive: true,\n })\n expect(mockInstallDeclaredPackages).toHaveBeenCalledWith(\n '/test/project',\n 'npm',\n expect.objectContaining({\n workDir: '/test/project',\n }),\n )\n expect(mockInstallNewPackages).not.toHaveBeenCalled()\n })\n\n test('installs declared packages with yarn', async () => {\n mockGetPackageManagerChoice.mockResolvedValueOnce({\n chosen: 'yarn',\n mostOptimal: 'yarn',\n })\n mockInstallDeclaredPackages.mockResolvedValueOnce()\n\n const {error} = await testCommand(Install, [])\n\n expect(error).toBeUndefined()\n expect(mockInstallDeclaredPackages).toHaveBeenCalledWith(\n '/test/project',\n 'yarn',\n expect.objectContaining({\n workDir: '/test/project',\n }),\n )\n })\n\n test('installs declared packages with pnpm', async () => {\n mockGetPackageManagerChoice.mockResolvedValueOnce({\n chosen: 'pnpm',\n mostOptimal: 'pnpm',\n })\n mockInstallDeclaredPackages.mockResolvedValueOnce()\n\n const {error} = await testCommand(Install, [])\n\n expect(error).toBeUndefined()\n expect(mockInstallDeclaredPackages).toHaveBeenCalledWith(\n '/test/project',\n 'pnpm',\n expect.objectContaining({\n workDir: '/test/project',\n }),\n )\n })\n\n test('installs declared packages with bun', async () => {\n mockGetPackageManagerChoice.mockResolvedValueOnce({\n chosen: 'bun',\n mostOptimal: 'bun',\n })\n mockInstallDeclaredPackages.mockResolvedValueOnce()\n\n const {error} = await testCommand(Install, [])\n\n expect(error).toBeUndefined()\n expect(mockInstallDeclaredPackages).toHaveBeenCalledWith(\n '/test/project',\n 'bun',\n expect.objectContaining({\n workDir: '/test/project',\n }),\n )\n })\n\n test('handles manual package manager selection', async () => {\n mockGetPackageManagerChoice.mockResolvedValueOnce({\n chosen: 'manual',\n mostOptimal: 'npm',\n })\n mockInstallDeclaredPackages.mockResolvedValueOnce()\n\n const {error} = await testCommand(Install, [])\n\n expect(error).toBeUndefined()\n expect(mockInstallDeclaredPackages).toHaveBeenCalledWith(\n '/test/project',\n 'manual',\n expect.objectContaining({\n workDir: '/test/project',\n }),\n )\n })\n })\n\n describe('install specific packages (with arguments)', () => {\n test('installs single package', async () => {\n mockGetPackageManagerChoice.mockResolvedValueOnce({\n chosen: 'npm',\n mostOptimal: 'npm',\n })\n mockInstallNewPackages.mockResolvedValueOnce()\n\n const {error} = await testCommand(Install, ['@sanity/vision'])\n\n expect(error).toBeUndefined()\n expect(mockInstallNewPackages).toHaveBeenCalledWith(\n {\n packageManager: 'npm',\n packages: ['@sanity/vision'],\n },\n expect.objectContaining({\n workDir: '/test/project',\n }),\n )\n expect(mockInstallDeclaredPackages).not.toHaveBeenCalled()\n })\n\n test('installs multiple packages', async () => {\n mockGetPackageManagerChoice.mockResolvedValueOnce({\n chosen: 'yarn',\n mostOptimal: 'yarn',\n })\n mockInstallNewPackages.mockResolvedValueOnce()\n\n const {error} = await testCommand(Install, ['@sanity/vision', 'react-icons', 'lodash'])\n\n expect(error).toBeUndefined()\n expect(mockInstallNewPackages).toHaveBeenCalledWith(\n {\n packageManager: 'yarn',\n packages: ['@sanity/vision', 'react-icons', 'lodash'],\n },\n expect.objectContaining({\n workDir: '/test/project',\n }),\n )\n expect(mockInstallDeclaredPackages).not.toHaveBeenCalled()\n })\n\n test('installs packages with different package managers', async () => {\n mockGetPackageManagerChoice.mockResolvedValueOnce({\n chosen: 'pnpm',\n mostOptimal: 'pnpm',\n })\n mockInstallNewPackages.mockResolvedValueOnce()\n\n const {error} = await testCommand(Install, ['some-package'])\n\n expect(error).toBeUndefined()\n expect(mockInstallNewPackages).toHaveBeenCalledWith(\n {\n packageManager: 'pnpm',\n packages: ['some-package'],\n },\n expect.objectContaining({\n workDir: '/test/project',\n }),\n )\n })\n })\n\n describe('error handling', () => {\n test('handles package manager choice failure', async () => {\n mockGetPackageManagerChoice.mockRejectedValueOnce(\n new Error('Failed to detect package manager'),\n )\n\n const {error} = await testCommand(Install, [])\n\n expect(error).toBeDefined()\n expect(error?.message).toContain('Failed to detect package manager')\n expect(mockInstallDeclaredPackages).not.toHaveBeenCalled()\n expect(mockInstallNewPackages).not.toHaveBeenCalled()\n })\n\n test('handles declared packages installation failure', async () => {\n mockGetPackageManagerChoice.mockResolvedValueOnce({\n chosen: 'npm',\n mostOptimal: 'npm',\n })\n mockInstallDeclaredPackages.mockRejectedValueOnce(new Error('Installation failed'))\n\n const {error} = await testCommand(Install, [])\n\n expect(error).toBeDefined()\n expect(error?.message).toContain('Installation failed')\n })\n\n test('handles new packages installation failure', async () => {\n mockGetPackageManagerChoice.mockResolvedValueOnce({\n chosen: 'npm',\n mostOptimal: 'npm',\n })\n mockInstallNewPackages.mockRejectedValueOnce(new Error('Package not found'))\n\n const {error} = await testCommand(Install, ['nonexistent-package'])\n\n expect(error).toBeDefined()\n expect(error?.message).toContain('Package not found')\n })\n })\n\n describe('integration with project root', () => {\n test('passes correct working directory to functions', async () => {\n mockGetPackageManagerChoice.mockResolvedValueOnce({\n chosen: 'npm',\n mostOptimal: 'npm',\n })\n mockInstallDeclaredPackages.mockResolvedValueOnce()\n\n await testCommand(Install, [])\n\n expect(mockGetPackageManagerChoice).toHaveBeenCalledWith('/test/project', {\n interactive: true,\n })\n expect(mockInstallDeclaredPackages).toHaveBeenCalledWith(\n '/test/project',\n 'npm',\n expect.objectContaining({\n workDir: '/test/project',\n }),\n )\n })\n\n test('provides output object to install functions', async () => {\n mockGetPackageManagerChoice.mockResolvedValueOnce({\n chosen: 'npm',\n mostOptimal: 'npm',\n })\n mockInstallNewPackages.mockResolvedValueOnce()\n\n await testCommand(Install, ['test-package'])\n\n expect(mockInstallNewPackages).toHaveBeenCalledWith(\n {\n packageManager: 'npm',\n packages: ['test-package'],\n },\n expect.objectContaining({\n output: expect.objectContaining({\n error: expect.any(Function),\n log: expect.any(Function),\n warn: expect.any(Function),\n }),\n workDir: '/test/project',\n }),\n )\n })\n })\n})\n"],"names":["runCommand","testCommand","afterEach","describe","expect","test","vi","installDeclaredPackages","installNewPackages","getPackageManagerChoice","Install","mock","findProjectRoot","fn","mockResolvedValue","directory","root","type","mockGetPackageManagerChoice","mocked","mockInstallDeclaredPackages","mockInstallNewPackages","clearAllMocks","stdout","toMatchInlineSnapshot","mockResolvedValueOnce","chosen","mostOptimal","error","toBeUndefined","toHaveBeenCalledWith","interactive","objectContaining","workDir","not","toHaveBeenCalled","packageManager","packages","mockRejectedValueOnce","Error","toBeDefined","message","toContain","output","any","Function","log","warn"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/commands/__tests__/install.test.ts"],"sourcesContent":["import {runCommand} from '@oclif/test'\nimport {testCommand} from '@sanity/cli-test'\nimport {afterEach, describe, expect, test, vi} from 'vitest'\n\nimport {\n installDeclaredPackages,\n installNewPackages,\n} from '../../util/packageManager/installPackages.js'\nimport {getPackageManagerChoice} from '../../util/packageManager/packageManagerChoice.js'\nimport {Install} from '../install.js'\n\nvi.mock('../../util/packageManager/packageManagerChoice.js', () => ({\n getPackageManagerChoice: vi.fn(),\n}))\n\nvi.mock('../../util/packageManager/installPackages.js', () => ({\n installDeclaredPackages: vi.fn(),\n installNewPackages: vi.fn(),\n}))\n\nconst mockGetPackageManagerChoice = vi.mocked(getPackageManagerChoice)\nconst mockInstallDeclaredPackages = vi.mocked(installDeclaredPackages)\nconst mockInstallNewPackages = vi.mocked(installNewPackages)\n\nconst defaultMocks = {\n projectRoot: {\n directory: '/test/project',\n path: '/test/project/sanity.config.ts',\n type: 'studio' as const,\n },\n}\n\nafterEach(() => {\n vi.clearAllMocks()\n})\n\ndescribe('#install', () => {\n test('help text is correct', async () => {\n const {stdout} = await runCommand('install --help')\n expect(stdout).toMatchInlineSnapshot(`\n \"Installs dependencies for Sanity Studio project\n\n USAGE\n $ sanity install [PACKAGES...]\n\n ARGUMENTS\n [PACKAGES...] Packages to install\n\n DESCRIPTION\n Installs dependencies for Sanity Studio project\n\n EXAMPLES\n $ sanity install\n\n $ sanity install @sanity/vision\n\n $ sanity install some-package another-package\n\n \"\n `)\n })\n\n describe('install declared packages (no arguments)', () => {\n test('installs declared packages with npm', async () => {\n mockGetPackageManagerChoice.mockResolvedValueOnce({\n chosen: 'npm',\n mostOptimal: 'npm',\n })\n mockInstallDeclaredPackages.mockResolvedValueOnce()\n\n const {error} = await testCommand(Install, [], {mocks: defaultMocks})\n\n expect(error).toBeUndefined()\n expect(mockGetPackageManagerChoice).toHaveBeenCalledWith('/test/project', {\n interactive: true,\n })\n expect(mockInstallDeclaredPackages).toHaveBeenCalledWith(\n '/test/project',\n 'npm',\n expect.objectContaining({\n workDir: '/test/project',\n }),\n )\n expect(mockInstallNewPackages).not.toHaveBeenCalled()\n })\n\n test('installs declared packages with yarn', async () => {\n mockGetPackageManagerChoice.mockResolvedValueOnce({\n chosen: 'yarn',\n mostOptimal: 'yarn',\n })\n mockInstallDeclaredPackages.mockResolvedValueOnce()\n\n const {error} = await testCommand(Install, [], {mocks: defaultMocks})\n\n expect(error).toBeUndefined()\n expect(mockInstallDeclaredPackages).toHaveBeenCalledWith(\n '/test/project',\n 'yarn',\n expect.objectContaining({\n workDir: '/test/project',\n }),\n )\n })\n\n test('installs declared packages with pnpm', async () => {\n mockGetPackageManagerChoice.mockResolvedValueOnce({\n chosen: 'pnpm',\n mostOptimal: 'pnpm',\n })\n mockInstallDeclaredPackages.mockResolvedValueOnce()\n\n const {error} = await testCommand(Install, [], {mocks: defaultMocks})\n\n expect(error).toBeUndefined()\n expect(mockInstallDeclaredPackages).toHaveBeenCalledWith(\n '/test/project',\n 'pnpm',\n expect.objectContaining({\n workDir: '/test/project',\n }),\n )\n })\n\n test('installs declared packages with bun', async () => {\n mockGetPackageManagerChoice.mockResolvedValueOnce({\n chosen: 'bun',\n mostOptimal: 'bun',\n })\n mockInstallDeclaredPackages.mockResolvedValueOnce()\n\n const {error} = await testCommand(Install, [], {mocks: defaultMocks})\n\n expect(error).toBeUndefined()\n expect(mockInstallDeclaredPackages).toHaveBeenCalledWith(\n '/test/project',\n 'bun',\n expect.objectContaining({\n workDir: '/test/project',\n }),\n )\n })\n\n test('handles manual package manager selection', async () => {\n mockGetPackageManagerChoice.mockResolvedValueOnce({\n chosen: 'manual',\n mostOptimal: 'npm',\n })\n mockInstallDeclaredPackages.mockResolvedValueOnce()\n\n const {error} = await testCommand(Install, [], {mocks: defaultMocks})\n\n expect(error).toBeUndefined()\n expect(mockInstallDeclaredPackages).toHaveBeenCalledWith(\n '/test/project',\n 'manual',\n expect.objectContaining({\n workDir: '/test/project',\n }),\n )\n })\n })\n\n describe('install specific packages (with arguments)', () => {\n test('installs single package', async () => {\n mockGetPackageManagerChoice.mockResolvedValueOnce({\n chosen: 'npm',\n mostOptimal: 'npm',\n })\n mockInstallNewPackages.mockResolvedValueOnce()\n\n const {error} = await testCommand(Install, ['@sanity/vision'], {mocks: defaultMocks})\n\n expect(error).toBeUndefined()\n expect(mockInstallNewPackages).toHaveBeenCalledWith(\n {\n packageManager: 'npm',\n packages: ['@sanity/vision'],\n },\n expect.objectContaining({\n workDir: '/test/project',\n }),\n )\n expect(mockInstallDeclaredPackages).not.toHaveBeenCalled()\n })\n\n test('installs multiple packages', async () => {\n mockGetPackageManagerChoice.mockResolvedValueOnce({\n chosen: 'yarn',\n mostOptimal: 'yarn',\n })\n mockInstallNewPackages.mockResolvedValueOnce()\n\n const {error} = await testCommand(Install, ['@sanity/vision', 'react-icons', 'lodash'], {\n mocks: defaultMocks,\n })\n\n expect(error).toBeUndefined()\n expect(mockInstallNewPackages).toHaveBeenCalledWith(\n {\n packageManager: 'yarn',\n packages: ['@sanity/vision', 'react-icons', 'lodash'],\n },\n expect.objectContaining({\n workDir: '/test/project',\n }),\n )\n expect(mockInstallDeclaredPackages).not.toHaveBeenCalled()\n })\n\n test('installs packages with different package managers', async () => {\n mockGetPackageManagerChoice.mockResolvedValueOnce({\n chosen: 'pnpm',\n mostOptimal: 'pnpm',\n })\n mockInstallNewPackages.mockResolvedValueOnce()\n\n const {error} = await testCommand(Install, ['some-package'], {mocks: defaultMocks})\n\n expect(error).toBeUndefined()\n expect(mockInstallNewPackages).toHaveBeenCalledWith(\n {\n packageManager: 'pnpm',\n packages: ['some-package'],\n },\n expect.objectContaining({\n workDir: '/test/project',\n }),\n )\n })\n })\n\n describe('error handling', () => {\n test('handles package manager choice failure', async () => {\n mockGetPackageManagerChoice.mockRejectedValueOnce(\n new Error('Failed to detect package manager'),\n )\n\n const {error} = await testCommand(Install, [], {mocks: defaultMocks})\n\n expect(error).toBeDefined()\n expect(error?.message).toContain('Failed to detect package manager')\n expect(mockInstallDeclaredPackages).not.toHaveBeenCalled()\n expect(mockInstallNewPackages).not.toHaveBeenCalled()\n })\n\n test('handles declared packages installation failure', async () => {\n mockGetPackageManagerChoice.mockResolvedValueOnce({\n chosen: 'npm',\n mostOptimal: 'npm',\n })\n mockInstallDeclaredPackages.mockRejectedValueOnce(new Error('Installation failed'))\n\n const {error} = await testCommand(Install, [], {mocks: defaultMocks})\n\n expect(error).toBeDefined()\n expect(error?.message).toContain('Installation failed')\n })\n\n test('handles new packages installation failure', async () => {\n mockGetPackageManagerChoice.mockResolvedValueOnce({\n chosen: 'npm',\n mostOptimal: 'npm',\n })\n mockInstallNewPackages.mockRejectedValueOnce(new Error('Package not found'))\n\n const {error} = await testCommand(Install, ['nonexistent-package'], {mocks: defaultMocks})\n\n expect(error).toBeDefined()\n expect(error?.message).toContain('Package not found')\n })\n })\n\n describe('integration with project root', () => {\n test('passes correct working directory to functions', async () => {\n mockGetPackageManagerChoice.mockResolvedValueOnce({\n chosen: 'npm',\n mostOptimal: 'npm',\n })\n mockInstallDeclaredPackages.mockResolvedValueOnce()\n\n await testCommand(Install, [], {mocks: defaultMocks})\n\n expect(mockGetPackageManagerChoice).toHaveBeenCalledWith('/test/project', {\n interactive: true,\n })\n expect(mockInstallDeclaredPackages).toHaveBeenCalledWith(\n '/test/project',\n 'npm',\n expect.objectContaining({\n workDir: '/test/project',\n }),\n )\n })\n\n test('provides output object to install functions', async () => {\n mockGetPackageManagerChoice.mockResolvedValueOnce({\n chosen: 'npm',\n mostOptimal: 'npm',\n })\n mockInstallNewPackages.mockResolvedValueOnce()\n\n await testCommand(Install, ['test-package'], {mocks: defaultMocks})\n\n expect(mockInstallNewPackages).toHaveBeenCalledWith(\n {\n packageManager: 'npm',\n packages: ['test-package'],\n },\n expect.objectContaining({\n output: expect.objectContaining({\n error: expect.any(Function),\n log: expect.any(Function),\n warn: expect.any(Function),\n }),\n workDir: '/test/project',\n }),\n )\n })\n })\n})\n"],"names":["runCommand","testCommand","afterEach","describe","expect","test","vi","installDeclaredPackages","installNewPackages","getPackageManagerChoice","Install","mock","fn","mockGetPackageManagerChoice","mocked","mockInstallDeclaredPackages","mockInstallNewPackages","defaultMocks","projectRoot","directory","path","type","clearAllMocks","stdout","toMatchInlineSnapshot","mockResolvedValueOnce","chosen","mostOptimal","error","mocks","toBeUndefined","toHaveBeenCalledWith","interactive","objectContaining","workDir","not","toHaveBeenCalled","packageManager","packages","mockRejectedValueOnce","Error","toBeDefined","message","toContain","output","any","Function","log","warn"],"mappings":"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"}
|