@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.
Files changed (291) hide show
  1. package/dist/actions/dev/startStudioDevServer.js +3 -8
  2. package/dist/actions/dev/startStudioDevServer.js.map +1 -1
  3. package/dist/actions/dev/types.d.ts +1 -3
  4. package/dist/actions/dev/types.js.map +1 -1
  5. package/dist/actions/documents/validate.d.ts +0 -2
  6. package/dist/actions/documents/validate.js +21 -1
  7. package/dist/actions/documents/validate.js.map +1 -1
  8. package/dist/actions/exec/execScript.js +1 -1
  9. package/dist/actions/exec/execScript.js.map +1 -1
  10. package/dist/actions/graphql/__tests__/getGraphQLAPIs.test.js +1 -1
  11. package/dist/actions/graphql/__tests__/getGraphQLAPIs.test.js.map +1 -1
  12. package/dist/actions/graphql/getGraphQLAPIs.js +1 -1
  13. package/dist/actions/graphql/getGraphQLAPIs.js.map +1 -1
  14. package/dist/actions/manifest/extractManifest.js +1 -4
  15. package/dist/actions/manifest/extractManifest.js.map +1 -1
  16. package/dist/actions/schema/deleteSchemaAction.d.ts +13 -5
  17. package/dist/actions/schema/deleteSchemaAction.js +12 -17
  18. package/dist/actions/schema/deleteSchemaAction.js.map +1 -1
  19. package/dist/actions/schema/deploySchemas.d.ts +15 -0
  20. package/dist/actions/schema/deploySchemas.js +98 -0
  21. package/dist/actions/schema/deploySchemas.js.map +1 -0
  22. package/dist/actions/schema/listSchemas.d.ts +12 -0
  23. package/dist/actions/schema/listSchemas.js +119 -0
  24. package/dist/actions/schema/listSchemas.js.map +1 -0
  25. package/dist/actions/schema/schemaStoreTypes.d.ts +0 -11
  26. package/dist/actions/schema/schemaStoreTypes.js.map +1 -1
  27. package/dist/actions/schema/utils/debug.d.ts +2 -0
  28. package/dist/actions/schema/utils/debug.js +5 -0
  29. package/dist/actions/schema/utils/debug.js.map +1 -0
  30. package/dist/actions/schema/utils/manifestExtractor.d.ts +3 -8
  31. package/dist/actions/schema/utils/manifestExtractor.js +12 -17
  32. package/dist/actions/schema/utils/manifestExtractor.js.map +1 -1
  33. package/dist/actions/schema/utils/manifestReader.d.ts +2 -9
  34. package/dist/actions/schema/utils/manifestReader.js +6 -12
  35. package/dist/actions/schema/utils/manifestReader.js.map +1 -1
  36. package/dist/actions/schema/utils/schemaStoreOutStrings.d.ts +0 -1
  37. package/dist/actions/schema/utils/schemaStoreOutStrings.js +1 -1
  38. package/dist/actions/schema/utils/schemaStoreOutStrings.js.map +1 -1
  39. package/dist/actions/schema/utils/schemaStoreValidation.d.ts +10 -62
  40. package/dist/actions/schema/utils/schemaStoreValidation.js +38 -125
  41. package/dist/actions/schema/utils/schemaStoreValidation.js.map +1 -1
  42. package/dist/actions/schema/utils/uniqByProjectIdDataset.d.ts +14 -0
  43. package/dist/actions/schema/utils/uniqByProjectIdDataset.js +9 -0
  44. package/dist/actions/schema/utils/uniqByProjectIdDataset.js.map +1 -0
  45. package/dist/actions/users/getMembersForProject.d.ts +1 -3
  46. package/dist/actions/users/getMembersForProject.js +6 -17
  47. package/dist/actions/users/getMembersForProject.js.map +1 -1
  48. package/dist/actions/users/types.d.ts +0 -11
  49. package/dist/actions/users/types.js.map +1 -1
  50. package/dist/commands/__tests__/debug.test.js +113 -220
  51. package/dist/commands/__tests__/debug.test.js.map +1 -1
  52. package/dist/commands/__tests__/deploy.test.js +325 -293
  53. package/dist/commands/__tests__/deploy.test.js.map +1 -1
  54. package/dist/commands/__tests__/dev.test.js +62 -19
  55. package/dist/commands/__tests__/dev.test.js.map +1 -1
  56. package/dist/commands/__tests__/init/init.authentication.test.js +40 -27
  57. package/dist/commands/__tests__/init/init.authentication.test.js.map +1 -1
  58. package/dist/commands/__tests__/init/init.create-new-project.test.js +84 -85
  59. package/dist/commands/__tests__/init/init.create-new-project.test.js.map +1 -1
  60. package/dist/commands/__tests__/init/init.plan.test.js +103 -44
  61. package/dist/commands/__tests__/init/init.plan.test.js.map +1 -1
  62. package/dist/commands/__tests__/init/init.setup.test.js +85 -29
  63. package/dist/commands/__tests__/init/init.setup.test.js.map +1 -1
  64. package/dist/commands/__tests__/install.test.js +46 -22
  65. package/dist/commands/__tests__/install.test.js.map +1 -1
  66. package/dist/commands/__tests__/logout.test.js +8 -5
  67. package/dist/commands/__tests__/logout.test.js.map +1 -1
  68. package/dist/commands/__tests__/manage.test.js +29 -24
  69. package/dist/commands/__tests__/manage.test.js.map +1 -1
  70. package/dist/commands/__tests__/versions.test.js +22 -14
  71. package/dist/commands/__tests__/versions.test.js.map +1 -1
  72. package/dist/commands/backup/__tests__/disable.test.js +72 -75
  73. package/dist/commands/backup/__tests__/disable.test.js.map +1 -1
  74. package/dist/commands/backup/__tests__/download.test.js +166 -77
  75. package/dist/commands/backup/__tests__/download.test.js.map +1 -1
  76. package/dist/commands/backup/__tests__/enable.test.js +109 -140
  77. package/dist/commands/backup/__tests__/enable.test.js.map +1 -1
  78. package/dist/commands/backup/__tests__/list.test.js +84 -75
  79. package/dist/commands/backup/__tests__/list.test.js.map +1 -1
  80. package/dist/commands/backup/disable.js +5 -11
  81. package/dist/commands/backup/disable.js.map +1 -1
  82. package/dist/commands/backup/enable.js +5 -11
  83. package/dist/commands/backup/enable.js.map +1 -1
  84. package/dist/commands/backup/list.js +7 -8
  85. package/dist/commands/backup/list.js.map +1 -1
  86. package/dist/commands/cors/__tests__/add.test.js +68 -38
  87. package/dist/commands/cors/__tests__/add.test.js.map +1 -1
  88. package/dist/commands/cors/__tests__/delete.test.js +52 -37
  89. package/dist/commands/cors/__tests__/delete.test.js.map +1 -1
  90. package/dist/commands/cors/__tests__/list.test.js +80 -57
  91. package/dist/commands/cors/__tests__/list.test.js.map +1 -1
  92. package/dist/commands/cors/add.js +5 -13
  93. package/dist/commands/cors/add.js.map +1 -1
  94. package/dist/commands/cors/delete.js +7 -15
  95. package/dist/commands/cors/delete.js.map +1 -1
  96. package/dist/commands/cors/list.js +2 -10
  97. package/dist/commands/cors/list.js.map +1 -1
  98. package/dist/commands/dataset/__tests__/copy.test.js +197 -89
  99. package/dist/commands/dataset/__tests__/copy.test.js.map +1 -1
  100. package/dist/commands/dataset/__tests__/create.test.js +147 -117
  101. package/dist/commands/dataset/__tests__/create.test.js.map +1 -1
  102. package/dist/commands/dataset/__tests__/delete.test.js +75 -68
  103. package/dist/commands/dataset/__tests__/delete.test.js.map +1 -1
  104. package/dist/commands/dataset/__tests__/export.test.js +123 -83
  105. package/dist/commands/dataset/__tests__/export.test.js.map +1 -1
  106. package/dist/commands/dataset/__tests__/list.test.js +107 -65
  107. package/dist/commands/dataset/__tests__/list.test.js.map +1 -1
  108. package/dist/commands/dataset/alias/__tests__/create.test.js +114 -74
  109. package/dist/commands/dataset/alias/__tests__/create.test.js.map +1 -1
  110. package/dist/commands/dataset/alias/__tests__/delete.test.js +40 -29
  111. package/dist/commands/dataset/alias/__tests__/delete.test.js.map +1 -1
  112. package/dist/commands/dataset/alias/__tests__/link.test.js +114 -74
  113. package/dist/commands/dataset/alias/__tests__/link.test.js.map +1 -1
  114. package/dist/commands/dataset/alias/__tests__/unlink.test.js +44 -29
  115. package/dist/commands/dataset/alias/__tests__/unlink.test.js.map +1 -1
  116. package/dist/commands/dataset/export.js +4 -4
  117. package/dist/commands/dataset/export.js.map +1 -1
  118. package/dist/commands/dataset/visibility/__tests__/get.test.js +48 -67
  119. package/dist/commands/dataset/visibility/__tests__/get.test.js.map +1 -1
  120. package/dist/commands/dataset/visibility/__tests__/set.test.js +76 -123
  121. package/dist/commands/dataset/visibility/__tests__/set.test.js.map +1 -1
  122. package/dist/commands/dev.js +0 -1
  123. package/dist/commands/dev.js.map +1 -1
  124. package/dist/commands/docs/__tests__/search.test.js +8 -7
  125. package/dist/commands/docs/__tests__/search.test.js.map +1 -1
  126. package/dist/commands/documents/__tests__/create.test.js +328 -265
  127. package/dist/commands/documents/__tests__/create.test.js.map +1 -1
  128. package/dist/commands/documents/__tests__/delete.test.js +119 -87
  129. package/dist/commands/documents/__tests__/delete.test.js.map +1 -1
  130. package/dist/commands/documents/__tests__/get.test.js +68 -95
  131. package/dist/commands/documents/__tests__/get.test.js.map +1 -1
  132. package/dist/commands/documents/__tests__/query.test.js +84 -189
  133. package/dist/commands/documents/__tests__/query.test.js.map +1 -1
  134. package/dist/commands/documents/__tests__/validate.test.js +52 -29
  135. package/dist/commands/documents/__tests__/validate.test.js.map +1 -1
  136. package/dist/commands/documents/create.d.ts +1 -0
  137. package/dist/commands/documents/create.js +10 -9
  138. package/dist/commands/documents/create.js.map +1 -1
  139. package/dist/commands/documents/delete.js +2 -3
  140. package/dist/commands/documents/delete.js.map +1 -1
  141. package/dist/commands/documents/get.js +2 -3
  142. package/dist/commands/documents/get.js.map +1 -1
  143. package/dist/commands/documents/query.js +2 -3
  144. package/dist/commands/documents/query.js.map +1 -1
  145. package/dist/commands/documents/validate.js +0 -20
  146. package/dist/commands/documents/validate.js.map +1 -1
  147. package/dist/commands/graphql/__tests__/list.test.js +57 -45
  148. package/dist/commands/graphql/__tests__/list.test.js.map +1 -1
  149. package/dist/commands/graphql/__tests__/undeploy.test.js +85 -59
  150. package/dist/commands/graphql/__tests__/undeploy.test.js.map +1 -1
  151. package/dist/commands/graphql/list.js +2 -2
  152. package/dist/commands/graphql/list.js.map +1 -1
  153. package/dist/commands/graphql/undeploy.js +4 -9
  154. package/dist/commands/graphql/undeploy.js.map +1 -1
  155. package/dist/commands/hook/__tests__/attempt.test.js +48 -33
  156. package/dist/commands/hook/__tests__/attempt.test.js.map +1 -1
  157. package/dist/commands/hook/__tests__/create.test.js +49 -51
  158. package/dist/commands/hook/__tests__/create.test.js.map +1 -1
  159. package/dist/commands/hook/__tests__/delete.test.js +43 -30
  160. package/dist/commands/hook/__tests__/delete.test.js.map +1 -1
  161. package/dist/commands/hook/__tests__/list.test.js +38 -31
  162. package/dist/commands/hook/__tests__/list.test.js.map +1 -1
  163. package/dist/commands/hook/__tests__/logs.test.js +68 -40
  164. package/dist/commands/hook/__tests__/logs.test.js.map +1 -1
  165. package/dist/commands/hook/create.js +2 -6
  166. package/dist/commands/hook/create.js.map +1 -1
  167. package/dist/commands/hook/delete.js +5 -17
  168. package/dist/commands/hook/delete.js.map +1 -1
  169. package/dist/commands/hook/list.js +2 -8
  170. package/dist/commands/hook/list.js.map +1 -1
  171. package/dist/commands/manifest/__tests__/extract.test.js +22 -13
  172. package/dist/commands/manifest/__tests__/extract.test.js.map +1 -1
  173. package/dist/commands/media/__tests__/create-aspect.test.js +41 -28
  174. package/dist/commands/media/__tests__/create-aspect.test.js.map +1 -1
  175. package/dist/commands/media/__tests__/delete-aspect.test.js +44 -35
  176. package/dist/commands/media/__tests__/delete-aspect.test.js.map +1 -1
  177. package/dist/commands/media/__tests__/deploy-aspect.test.js +67 -80
  178. package/dist/commands/media/__tests__/deploy-aspect.test.js.map +1 -1
  179. package/dist/commands/media/__tests__/export.test.js +365 -66
  180. package/dist/commands/media/__tests__/export.test.js.map +1 -1
  181. package/dist/commands/media/__tests__/import.test.js +171 -105
  182. package/dist/commands/media/__tests__/import.test.js.map +1 -1
  183. package/dist/commands/media/export.js +2 -2
  184. package/dist/commands/media/export.js.map +1 -1
  185. package/dist/commands/media/import.js +2 -2
  186. package/dist/commands/media/import.js.map +1 -1
  187. package/dist/commands/projects/__tests__/list.test.js +5 -4
  188. package/dist/commands/projects/__tests__/list.test.js.map +1 -1
  189. package/dist/commands/projects/list.js +2 -6
  190. package/dist/commands/projects/list.js.map +1 -1
  191. package/dist/commands/schema/__tests__/delete.test.js +396 -151
  192. package/dist/commands/schema/__tests__/delete.test.js.map +1 -1
  193. package/dist/commands/schema/__tests__/deploy.test.js +348 -0
  194. package/dist/commands/schema/__tests__/deploy.test.js.map +1 -0
  195. package/dist/commands/schema/__tests__/extract.test.js +19 -11
  196. package/dist/commands/schema/__tests__/extract.test.js.map +1 -1
  197. package/dist/commands/schema/__tests__/list.test.js +399 -0
  198. package/dist/commands/schema/__tests__/list.test.js.map +1 -0
  199. package/dist/commands/schema/__tests__/validate.test.js +27 -10
  200. package/dist/commands/schema/__tests__/validate.test.js.map +1 -1
  201. package/dist/commands/schema/delete.d.ts +1 -1
  202. package/dist/commands/schema/delete.js +20 -23
  203. package/dist/commands/schema/delete.js.map +1 -1
  204. package/dist/commands/schema/deploy.d.ts +16 -0
  205. package/dist/commands/schema/deploy.js +98 -0
  206. package/dist/commands/schema/deploy.js.map +1 -0
  207. package/dist/commands/schema/list.d.ts +15 -0
  208. package/dist/commands/schema/list.js +104 -0
  209. package/dist/commands/schema/list.js.map +1 -0
  210. package/dist/commands/telemetry/__tests__/disable.test.js +7 -5
  211. package/dist/commands/telemetry/__tests__/disable.test.js.map +1 -1
  212. package/dist/commands/telemetry/__tests__/enable.test.js +7 -5
  213. package/dist/commands/telemetry/__tests__/enable.test.js.map +1 -1
  214. package/dist/commands/telemetry/__tests__/status.test.js +7 -5
  215. package/dist/commands/telemetry/__tests__/status.test.js.map +1 -1
  216. package/dist/commands/tokens/__tests__/add.test.js +55 -40
  217. package/dist/commands/tokens/__tests__/add.test.js.map +1 -1
  218. package/dist/commands/tokens/__tests__/delete.test.js +72 -42
  219. package/dist/commands/tokens/__tests__/delete.test.js.map +1 -1
  220. package/dist/commands/tokens/__tests__/list.test.js +87 -60
  221. package/dist/commands/tokens/__tests__/list.test.js.map +1 -1
  222. package/dist/commands/tokens/add.js +3 -5
  223. package/dist/commands/tokens/add.js.map +1 -1
  224. package/dist/commands/users/__tests__/invite.test.js +100 -79
  225. package/dist/commands/users/__tests__/invite.test.js.map +1 -1
  226. package/dist/commands/users/__tests__/list.test.js +186 -180
  227. package/dist/commands/users/__tests__/list.test.js.map +1 -1
  228. package/dist/commands/users/invite.js +6 -17
  229. package/dist/commands/users/invite.js.map +1 -1
  230. package/dist/commands/users/list.js +4 -7
  231. package/dist/commands/users/list.js.map +1 -1
  232. package/dist/config/createCliConfig.d.ts +4 -4
  233. package/dist/services/backup.d.ts +8 -0
  234. package/dist/services/backup.js +19 -0
  235. package/dist/services/backup.js.map +1 -1
  236. package/dist/services/cors.d.ts +23 -0
  237. package/dist/services/cors.js +38 -0
  238. package/dist/services/cors.js.map +1 -0
  239. package/dist/services/graphql.d.ts +7 -0
  240. package/dist/services/graphql.js +11 -0
  241. package/dist/services/graphql.js.map +1 -1
  242. package/dist/services/hooks.d.ts +2 -0
  243. package/dist/services/hooks.js +19 -0
  244. package/dist/services/hooks.js.map +1 -1
  245. package/dist/services/organizations.d.ts +1 -1
  246. package/dist/services/organizations.js +1 -1
  247. package/dist/services/organizations.js.map +1 -1
  248. package/dist/services/projects.d.ts +11 -0
  249. package/dist/services/projects.js +41 -0
  250. package/dist/services/projects.js.map +1 -1
  251. package/dist/services/schemas.d.ts +4 -0
  252. package/dist/services/schemas.js +40 -0
  253. package/dist/services/schemas.js.map +1 -0
  254. package/dist/services/user.d.ts +8 -0
  255. package/dist/services/user.js +15 -2
  256. package/dist/services/user.js.map +1 -1
  257. package/dist/util/__tests__/getCliVersion.test.js +2 -2
  258. package/dist/util/__tests__/getCliVersion.test.js.map +1 -1
  259. package/dist/util/errorMessages.d.ts +1 -0
  260. package/dist/util/errorMessages.js +1 -0
  261. package/dist/util/errorMessages.js.map +1 -1
  262. package/dist/util/getCliVersion.js +1 -1
  263. package/dist/util/getCliVersion.js.map +1 -1
  264. package/dist/util/readPackageJson.d.ts +1 -15
  265. package/dist/util/readPackageJson.js +1 -1
  266. package/dist/util/readPackageJson.js.map +1 -1
  267. package/dist/util/uniqBy.d.ts +1 -0
  268. package/dist/util/uniqBy.js +14 -0
  269. package/dist/util/uniqBy.js.map +1 -0
  270. package/oclif.manifest.json +172 -27
  271. package/package.json +27 -28
  272. package/dist/actions/cors/constants.d.ts +0 -1
  273. package/dist/actions/cors/constants.js +0 -3
  274. package/dist/actions/cors/constants.js.map +0 -1
  275. package/dist/actions/cors/types.d.ts +0 -9
  276. package/dist/actions/cors/types.js +0 -3
  277. package/dist/actions/cors/types.js.map +0 -1
  278. package/dist/actions/schema/__tests__/deleteSchemaAction.test.js +0 -294
  279. package/dist/actions/schema/__tests__/deleteSchemaAction.test.js.map +0 -1
  280. package/dist/actions/schema/schemaStoreConstants.d.ts +0 -1
  281. package/dist/actions/schema/schemaStoreConstants.js +0 -4
  282. package/dist/actions/schema/schemaStoreConstants.js.map +0 -1
  283. package/dist/actions/schema/utils/schemaActionHelpers.d.ts +0 -1
  284. package/dist/actions/schema/utils/schemaActionHelpers.js +0 -5
  285. package/dist/actions/schema/utils/schemaActionHelpers.js.map +0 -1
  286. package/dist/actions/schema/utils/schemaApiClient.d.ts +0 -6
  287. package/dist/actions/schema/utils/schemaApiClient.js +0 -17
  288. package/dist/actions/schema/utils/schemaApiClient.js.map +0 -1
  289. package/dist/actions/users/apiVersion.d.ts +0 -6
  290. package/dist/actions/users/apiVersion.js +0 -7
  291. package/dist/actions/users/apiVersion.js.map +0 -1
@@ -1,5 +1,4 @@
1
1
  import { runCommand } from '@oclif/test';
2
- import { getCliConfig } from '@sanity/cli-core';
3
2
  import { input, select } from '@sanity/cli-core/ux';
4
3
  import { mockApi, testCommand } from '@sanity/cli-test';
5
4
  import nock from 'nock';
@@ -7,25 +6,6 @@ import { afterEach, describe, expect, test, vi } from 'vitest';
7
6
  import { TOKENS_API_VERSION } from '../../../actions/tokens/constants.js';
8
7
  import { NO_PROJECT_ID } from '../../../util/errorMessages.js';
9
8
  import { AddTokenCommand } from '../add.js';
10
- // Mock the config functions with relative paths
11
- vi.mock('../../../../../cli-core/src/config/findProjectRoot.js', ()=>({
12
- findProjectRoot: vi.fn().mockResolvedValue({
13
- directory: '/test/path',
14
- root: '/test/path',
15
- type: 'studio'
16
- })
17
- }));
18
- vi.mock('../../../../../cli-core/src/config/cli/getCliConfig.js', ()=>({
19
- getCliConfig: vi.fn().mockResolvedValue({
20
- api: {
21
- projectId: 'test-project'
22
- }
23
- })
24
- }));
25
- vi.mock('../../../../../cli-core/src/services/getCliToken.js', ()=>({
26
- getCliToken: vi.fn().mockResolvedValue('test-token')
27
- }));
28
- // Mock inquirer prompts
29
9
  vi.mock('@sanity/cli-core/ux', async ()=>{
30
10
  const actual = await vi.importActual('@sanity/cli-core/ux');
31
11
  return {
@@ -36,10 +16,21 @@ vi.mock('@sanity/cli-core/ux', async ()=>{
36
16
  });
37
17
  const mockedInput = vi.mocked(input);
38
18
  const mockedSelect = vi.mocked(select);
39
- const mockedGetCliConfig = vi.mocked(getCliConfig);
40
- vi.mock('../../../../../cli-core/src/util/isInteractive.js', ()=>({
41
- isInteractive: vi.fn().mockReturnValue(true)
42
- }));
19
+ const testProjectId = 'test-project';
20
+ const defaultMocks = {
21
+ cliConfig: {
22
+ api: {
23
+ projectId: testProjectId
24
+ }
25
+ },
26
+ isInteractive: true,
27
+ projectRoot: {
28
+ directory: '/test/path',
29
+ path: '/test/path/sanity.config.ts',
30
+ type: 'studio'
31
+ },
32
+ token: 'test-token'
33
+ };
43
34
  describe('#tokens:add', ()=>{
44
35
  afterEach(()=>{
45
36
  vi.clearAllMocks();
@@ -98,7 +89,9 @@ describe('#tokens:add', ()=>{
98
89
  }).reply(200, mockToken);
99
90
  const { stdout } = await testCommand(AddTokenCommand, [
100
91
  'My Test Token'
101
- ]);
92
+ ], {
93
+ mocks: defaultMocks
94
+ });
102
95
  expect(stdout).toContain('Token created successfully!');
103
96
  expect(stdout).toContain('Label: My Test Token');
104
97
  expect(stdout).toContain('ID: token-123');
@@ -151,7 +144,9 @@ describe('#tokens:add', ()=>{
151
144
  const { stdout } = await testCommand(AddTokenCommand, [
152
145
  'Editor Token',
153
146
  '--role=editor'
154
- ]);
147
+ ], {
148
+ mocks: defaultMocks
149
+ });
155
150
  expect(stdout).toContain('Token created successfully!');
156
151
  expect(stdout).toContain('Label: Editor Token');
157
152
  expect(stdout).toContain('Role: Editor');
@@ -193,7 +188,9 @@ describe('#tokens:add', ()=>{
193
188
  const { stdout } = await testCommand(AddTokenCommand, [
194
189
  'JSON Token',
195
190
  '--json'
196
- ]);
191
+ ], {
192
+ mocks: defaultMocks
193
+ });
197
194
  const parsedOutput = JSON.parse(stdout);
198
195
  expect(parsedOutput).toEqual(mockToken);
199
196
  });
@@ -219,7 +216,9 @@ describe('#tokens:add', ()=>{
219
216
  const { stdout } = await testCommand(AddTokenCommand, [
220
217
  'Unattended Token',
221
218
  '--yes'
222
- ]);
219
+ ], {
220
+ mocks: defaultMocks
221
+ });
223
222
  expect(stdout).toContain('Token created successfully!');
224
223
  expect(stdout).toContain('Label: Unattended Token');
225
224
  });
@@ -242,7 +241,9 @@ describe('#tokens:add', ()=>{
242
241
  const { error } = await testCommand(AddTokenCommand, [
243
242
  'Test Token',
244
243
  '--role=invalid'
245
- ]);
244
+ ], {
245
+ mocks: defaultMocks
246
+ });
246
247
  expect(error).toBeInstanceOf(Error);
247
248
  expect(error?.message).toContain('Invalid role "invalid"');
248
249
  expect(error?.message).toContain('Available roles: viewer');
@@ -273,21 +274,27 @@ describe('#tokens:add', ()=>{
273
274
  });
274
275
  const { error } = await testCommand(AddTokenCommand, [
275
276
  'Failed Token'
276
- ]);
277
+ ], {
278
+ mocks: defaultMocks
279
+ });
277
280
  expect(error).toBeInstanceOf(Error);
278
281
  expect(error?.message).toContain('Token creation failed');
279
282
  expect(error?.message).toContain('Internal Server Error');
280
283
  expect(error?.oclif?.exit).toBe(1);
281
284
  });
282
285
  test('throws error when no project ID is found', async ()=>{
283
- mockedGetCliConfig.mockResolvedValueOnce({
284
- api: {
285
- projectId: undefined
286
- }
287
- });
288
286
  const { error } = await testCommand(AddTokenCommand, [
289
287
  'Test Token'
290
- ]);
288
+ ], {
289
+ mocks: {
290
+ ...defaultMocks,
291
+ cliConfig: {
292
+ api: {
293
+ projectId: undefined
294
+ }
295
+ }
296
+ }
297
+ });
291
298
  expect(error).toBeInstanceOf(Error);
292
299
  expect(error?.message).toEqual(NO_PROJECT_ID);
293
300
  expect(error?.oclif?.exit).toBe(1);
@@ -310,7 +317,9 @@ describe('#tokens:add', ()=>{
310
317
  }).reply(200, mockRoles);
311
318
  const { error } = await testCommand(AddTokenCommand, [
312
319
  'Test Token'
313
- ]);
320
+ ], {
321
+ mocks: defaultMocks
322
+ });
314
323
  expect(error).toBeInstanceOf(Error);
315
324
  expect(error?.message).toContain('No roles available for tokens');
316
325
  expect(error?.oclif?.exit).toBe(1);
@@ -350,7 +359,9 @@ describe('#tokens:add', ()=>{
350
359
  method: 'post',
351
360
  uri: '/projects/test-project/tokens'
352
361
  }).reply(200, mockToken);
353
- const { stdout } = await testCommand(AddTokenCommand, []);
362
+ const { stdout } = await testCommand(AddTokenCommand, [], {
363
+ mocks: defaultMocks
364
+ });
354
365
  expect(mockedInput).toHaveBeenCalledWith({
355
366
  message: 'Token label:',
356
367
  validate: expect.any(Function)
@@ -394,7 +405,9 @@ describe('#tokens:add', ()=>{
394
405
  method: 'post',
395
406
  uri: '/projects/test-project/tokens'
396
407
  }).reply(200, mockToken);
397
- await testCommand(AddTokenCommand, []);
408
+ await testCommand(AddTokenCommand, [], {
409
+ mocks: defaultMocks
410
+ });
398
411
  // Test that the validation function correctly rejects empty and whitespace-only strings
399
412
  const inputCall = mockedInput.mock.calls[0];
400
413
  expect(inputCall).toBeDefined();
@@ -409,7 +422,9 @@ describe('#tokens:add', ()=>{
409
422
  test('throws error when no label provided in non-interactive mode with --yes flag', async ()=>{
410
423
  const { error } = await testCommand(AddTokenCommand, [
411
424
  '--yes'
412
- ]);
425
+ ], {
426
+ mocks: defaultMocks
427
+ });
413
428
  expect(error).toBeInstanceOf(Error);
414
429
  expect(error?.message).toContain('Token label is required in non-interactive mode');
415
430
  expect(error?.message).toContain('Provide a label as an argument');
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/commands/tokens/__tests__/add.test.ts"],"sourcesContent":["import {runCommand} from '@oclif/test'\nimport {getCliConfig} from '@sanity/cli-core'\nimport {input, select} from '@sanity/cli-core/ux'\nimport {mockApi, testCommand} from '@sanity/cli-test'\nimport nock from 'nock'\nimport {afterEach, describe, expect, test, vi} from 'vitest'\n\nimport {TOKENS_API_VERSION} from '../../../actions/tokens/constants.js'\nimport {NO_PROJECT_ID} from '../../../util/errorMessages.js'\nimport {AddTokenCommand} from '../add.js'\n\n// Mock the config functions with relative paths\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\n// Mock inquirer prompts\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})\nconst mockedInput = vi.mocked(input)\nconst mockedSelect = vi.mocked(select)\nconst mockedGetCliConfig = vi.mocked(getCliConfig)\n\nvi.mock('../../../../../cli-core/src/util/isInteractive.js', () => ({\n isInteractive: vi.fn().mockReturnValue(true),\n}))\n\ndescribe('#tokens:add', () => {\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(['tokens add', '--help'])\n\n expect(stdout).toContain('Create a new API token for this project')\n })\n\n test('creates token with label argument and default role', async () => {\n const mockRoles = [\n {\n appliesToRobots: true,\n appliesToUsers: true,\n description: 'Can read documents',\n isCustom: false,\n name: 'viewer',\n projectId: 'test-project',\n title: 'Viewer',\n },\n {\n appliesToRobots: true,\n appliesToUsers: true,\n description: 'Can read and write documents',\n isCustom: false,\n name: 'editor',\n projectId: 'test-project',\n title: 'Editor',\n },\n ]\n\n const mockToken = {\n id: 'token-123',\n key: 'sk_test_abcd1234',\n label: 'My Test Token',\n projectUserId: 'user-123',\n roles: [\n {\n name: 'viewer',\n title: 'Viewer',\n },\n ],\n }\n\n mockApi({\n apiVersion: TOKENS_API_VERSION,\n uri: '/projects/test-project/roles',\n }).reply(200, mockRoles)\n\n mockApi({\n apiVersion: TOKENS_API_VERSION,\n method: 'post',\n uri: '/projects/test-project/tokens',\n }).reply(200, mockToken)\n\n const {stdout} = await testCommand(AddTokenCommand, ['My Test Token'])\n\n expect(stdout).toContain('Token created successfully!')\n expect(stdout).toContain('Label: My Test Token')\n expect(stdout).toContain('ID: token-123')\n expect(stdout).toContain('Role: Viewer')\n expect(stdout).toContain('Token: sk_test_abcd1234')\n expect(stdout).toContain('Copy the token above')\n })\n\n test('creates token with specific role', async () => {\n const mockRoles = [\n {\n appliesToRobots: true,\n appliesToUsers: true,\n description: 'Can read documents',\n isCustom: false,\n name: 'viewer',\n projectId: 'test-project',\n title: 'Viewer',\n },\n {\n appliesToRobots: true,\n appliesToUsers: true,\n description: 'Can read and write documents',\n isCustom: false,\n name: 'editor',\n projectId: 'test-project',\n title: 'Editor',\n },\n ]\n\n const mockToken = {\n id: 'token-456',\n key: 'sk_test_editor1234',\n label: 'Editor Token',\n projectUserId: 'user-123',\n roles: [\n {\n name: 'editor',\n title: 'Editor',\n },\n ],\n }\n\n mockApi({\n apiVersion: TOKENS_API_VERSION,\n uri: '/projects/test-project/roles',\n }).reply(200, mockRoles)\n\n mockApi({\n apiVersion: TOKENS_API_VERSION,\n method: 'post',\n uri: '/projects/test-project/tokens',\n }).reply(200, mockToken)\n\n const {stdout} = await testCommand(AddTokenCommand, ['Editor Token', '--role=editor'])\n\n expect(stdout).toContain('Token created successfully!')\n expect(stdout).toContain('Label: Editor Token')\n expect(stdout).toContain('Role: Editor')\n expect(stdout).toContain('Token: sk_test_editor1234')\n })\n\n test('outputs JSON when --json flag is used', async () => {\n const mockRoles = [\n {\n appliesToRobots: true,\n appliesToUsers: true,\n description: 'Can read documents',\n isCustom: false,\n name: 'viewer',\n projectId: 'test-project',\n title: 'Viewer',\n },\n ]\n\n const mockToken = {\n id: 'token-json',\n key: 'sk_test_json1234',\n label: 'JSON Token',\n projectUserId: 'user-123',\n roles: [\n {\n name: 'viewer',\n title: 'Viewer',\n },\n ],\n }\n\n mockApi({\n apiVersion: TOKENS_API_VERSION,\n uri: '/projects/test-project/roles',\n }).reply(200, mockRoles)\n\n mockApi({\n apiVersion: TOKENS_API_VERSION,\n method: 'post',\n uri: '/projects/test-project/tokens',\n }).reply(200, mockToken)\n\n const {stdout} = await testCommand(AddTokenCommand, ['JSON Token', '--json'])\n\n const parsedOutput = JSON.parse(stdout)\n expect(parsedOutput).toEqual(mockToken)\n })\n\n test('works in unattended mode with --yes flag', async () => {\n const mockToken = {\n id: 'token-unattended',\n key: 'sk_test_unattended1234',\n label: 'Unattended Token',\n projectUserId: 'user-123',\n roles: [\n {\n name: 'viewer',\n title: 'Viewer',\n },\n ],\n }\n\n // Only mock the token creation API, not the roles API since unattended mode uses default role\n mockApi({\n apiVersion: TOKENS_API_VERSION,\n method: 'post',\n uri: '/projects/test-project/tokens',\n }).reply(200, mockToken)\n\n const {stdout} = await testCommand(AddTokenCommand, ['Unattended Token', '--yes'])\n\n expect(stdout).toContain('Token created successfully!')\n expect(stdout).toContain('Label: Unattended Token')\n })\n\n test('handles invalid role error', async () => {\n const mockRoles = [\n {\n appliesToRobots: true,\n appliesToUsers: true,\n description: 'Can read documents',\n isCustom: false,\n name: 'viewer',\n projectId: 'test-project',\n title: 'Viewer',\n },\n ]\n\n mockApi({\n apiVersion: TOKENS_API_VERSION,\n uri: '/projects/test-project/roles',\n }).reply(200, mockRoles)\n\n const {error} = await testCommand(AddTokenCommand, ['Test Token', '--role=invalid'])\n\n expect(error).toBeInstanceOf(Error)\n expect(error?.message).toContain('Invalid role \"invalid\"')\n expect(error?.message).toContain('Available roles: viewer')\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test('handles API error during token creation', async () => {\n const mockRoles = [\n {\n appliesToRobots: true,\n appliesToUsers: true,\n description: 'Can read documents',\n isCustom: false,\n name: 'viewer',\n projectId: 'test-project',\n title: 'Viewer',\n },\n ]\n\n mockApi({\n apiVersion: TOKENS_API_VERSION,\n uri: '/projects/test-project/roles',\n }).reply(200, mockRoles)\n\n mockApi({\n apiVersion: TOKENS_API_VERSION,\n method: 'post',\n uri: '/projects/test-project/tokens',\n }).reply(500, {message: 'Internal Server Error'})\n\n const {error} = await testCommand(AddTokenCommand, ['Failed Token'])\n\n expect(error).toBeInstanceOf(Error)\n expect(error?.message).toContain('Token creation failed')\n expect(error?.message).toContain('Internal Server Error')\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test('throws error when no project ID is found', async () => {\n mockedGetCliConfig.mockResolvedValueOnce({\n api: {\n projectId: undefined,\n },\n })\n\n const {error} = await testCommand(AddTokenCommand, ['Test Token'])\n\n expect(error).toBeInstanceOf(Error)\n expect(error?.message).toEqual(NO_PROJECT_ID)\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test('handles no roles available for tokens', async () => {\n const mockRoles = [\n {\n appliesToRobots: false, // Not applicable to robots\n appliesToUsers: true,\n description: 'Full access',\n isCustom: false,\n name: 'admin',\n projectId: 'test-project',\n title: 'Admin',\n },\n ]\n\n mockApi({\n apiVersion: TOKENS_API_VERSION,\n uri: '/projects/test-project/roles',\n }).reply(200, mockRoles)\n\n const {error} = await testCommand(AddTokenCommand, ['Test Token'])\n\n expect(error).toBeInstanceOf(Error)\n expect(error?.message).toContain('No roles available for tokens')\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test('prompts for label when not provided in interactive mode', async () => {\n const mockRoles = [\n {\n appliesToRobots: true,\n appliesToUsers: true,\n description: 'Can read documents',\n isCustom: false,\n name: 'viewer',\n projectId: 'test-project',\n title: 'Viewer',\n },\n ]\n\n const mockToken = {\n id: 'token-prompted',\n key: 'sk_test_prompted1234',\n label: 'Prompted Label',\n projectUserId: 'user-123',\n roles: [\n {\n name: 'viewer',\n title: 'Viewer',\n },\n ],\n }\n\n mockedInput.mockResolvedValueOnce('Prompted Label')\n mockedSelect.mockResolvedValueOnce('viewer')\n\n mockApi({\n apiVersion: TOKENS_API_VERSION,\n uri: '/projects/test-project/roles',\n }).reply(200, mockRoles)\n\n mockApi({\n apiVersion: TOKENS_API_VERSION,\n method: 'post',\n uri: '/projects/test-project/tokens',\n }).reply(200, mockToken)\n\n const {stdout} = await testCommand(AddTokenCommand, [])\n\n expect(mockedInput).toHaveBeenCalledWith({\n message: 'Token label:',\n validate: expect.any(Function),\n })\n expect(stdout).toContain('Token created successfully!')\n expect(stdout).toContain('Label: Prompted Label')\n })\n\n test('validates label input - rejects empty label', async () => {\n // Mock input to capture the validation function and return a valid label\n mockedInput.mockResolvedValueOnce('Valid Label')\n mockedSelect.mockResolvedValueOnce('viewer')\n\n const mockRoles = [\n {\n appliesToRobots: true,\n appliesToUsers: true,\n description: 'Can read documents',\n isCustom: false,\n name: 'viewer',\n projectId: 'test-project',\n title: 'Viewer',\n },\n ]\n\n const mockToken = {\n id: 'token-validated',\n key: 'sk_test_validated1234',\n label: 'Valid Label',\n projectUserId: 'user-123',\n roles: [\n {\n name: 'viewer',\n title: 'Viewer',\n },\n ],\n }\n\n mockApi({\n apiVersion: TOKENS_API_VERSION,\n uri: '/projects/test-project/roles',\n }).reply(200, mockRoles)\n\n mockApi({\n apiVersion: TOKENS_API_VERSION,\n method: 'post',\n uri: '/projects/test-project/tokens',\n }).reply(200, mockToken)\n\n await testCommand(AddTokenCommand, [])\n\n // Test that the validation function correctly rejects empty and whitespace-only strings\n const inputCall = mockedInput.mock.calls[0]\n expect(inputCall).toBeDefined()\n const options = inputCall[0]\n expect(options.validate).toBeDefined()\n\n if (options.validate) {\n expect(options.validate('')).toBe('Label cannot be empty')\n expect(options.validate(' ')).toBe('Label cannot be empty')\n expect(options.validate('Valid Label')).toBe(true)\n }\n })\n\n test('throws error when no label provided in non-interactive mode with --yes flag', async () => {\n const {error} = await testCommand(AddTokenCommand, ['--yes'])\n\n expect(error).toBeInstanceOf(Error)\n expect(error?.message).toContain('Token label is required in non-interactive mode')\n expect(error?.message).toContain('Provide a label as an argument')\n expect(error?.oclif?.exit).toBe(1)\n })\n})\n"],"names":["runCommand","getCliConfig","input","select","mockApi","testCommand","nock","afterEach","describe","expect","test","vi","TOKENS_API_VERSION","NO_PROJECT_ID","AddTokenCommand","mock","findProjectRoot","fn","mockResolvedValue","directory","root","type","api","projectId","getCliToken","actual","importActual","mockedInput","mocked","mockedSelect","mockedGetCliConfig","isInteractive","mockReturnValue","clearAllMocks","pending","pendingMocks","cleanAll","toEqual","stdout","toContain","mockRoles","appliesToRobots","appliesToUsers","description","isCustom","name","title","mockToken","id","key","label","projectUserId","roles","apiVersion","uri","reply","method","parsedOutput","JSON","parse","error","toBeInstanceOf","Error","message","oclif","exit","toBe","mockResolvedValueOnce","undefined","toHaveBeenCalledWith","validate","any","Function","inputCall","calls","toBeDefined","options"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../src/commands/tokens/__tests__/add.test.ts"],"sourcesContent":["import {runCommand} from '@oclif/test'\nimport {input, select} from '@sanity/cli-core/ux'\nimport {mockApi, testCommand} from '@sanity/cli-test'\nimport nock from 'nock'\nimport {afterEach, describe, expect, test, vi} from 'vitest'\n\nimport {TOKENS_API_VERSION} from '../../../actions/tokens/constants.js'\nimport {NO_PROJECT_ID} from '../../../util/errorMessages.js'\nimport {AddTokenCommand} from '../add.js'\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\nconst mockedInput = vi.mocked(input)\nconst mockedSelect = vi.mocked(select)\n\nconst testProjectId = 'test-project'\n\nconst defaultMocks = {\n cliConfig: {api: {projectId: testProjectId}},\n isInteractive: true,\n projectRoot: {\n directory: '/test/path',\n path: '/test/path/sanity.config.ts',\n type: 'studio' as const,\n },\n token: 'test-token',\n}\n\ndescribe('#tokens:add', () => {\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(['tokens add', '--help'])\n\n expect(stdout).toContain('Create a new API token for this project')\n })\n\n test('creates token with label argument and default role', async () => {\n const mockRoles = [\n {\n appliesToRobots: true,\n appliesToUsers: true,\n description: 'Can read documents',\n isCustom: false,\n name: 'viewer',\n projectId: 'test-project',\n title: 'Viewer',\n },\n {\n appliesToRobots: true,\n appliesToUsers: true,\n description: 'Can read and write documents',\n isCustom: false,\n name: 'editor',\n projectId: 'test-project',\n title: 'Editor',\n },\n ]\n\n const mockToken = {\n id: 'token-123',\n key: 'sk_test_abcd1234',\n label: 'My Test Token',\n projectUserId: 'user-123',\n roles: [\n {\n name: 'viewer',\n title: 'Viewer',\n },\n ],\n }\n\n mockApi({\n apiVersion: TOKENS_API_VERSION,\n uri: '/projects/test-project/roles',\n }).reply(200, mockRoles)\n\n mockApi({\n apiVersion: TOKENS_API_VERSION,\n method: 'post',\n uri: '/projects/test-project/tokens',\n }).reply(200, mockToken)\n\n const {stdout} = await testCommand(AddTokenCommand, ['My Test Token'], {mocks: defaultMocks})\n\n expect(stdout).toContain('Token created successfully!')\n expect(stdout).toContain('Label: My Test Token')\n expect(stdout).toContain('ID: token-123')\n expect(stdout).toContain('Role: Viewer')\n expect(stdout).toContain('Token: sk_test_abcd1234')\n expect(stdout).toContain('Copy the token above')\n })\n\n test('creates token with specific role', async () => {\n const mockRoles = [\n {\n appliesToRobots: true,\n appliesToUsers: true,\n description: 'Can read documents',\n isCustom: false,\n name: 'viewer',\n projectId: 'test-project',\n title: 'Viewer',\n },\n {\n appliesToRobots: true,\n appliesToUsers: true,\n description: 'Can read and write documents',\n isCustom: false,\n name: 'editor',\n projectId: 'test-project',\n title: 'Editor',\n },\n ]\n\n const mockToken = {\n id: 'token-456',\n key: 'sk_test_editor1234',\n label: 'Editor Token',\n projectUserId: 'user-123',\n roles: [\n {\n name: 'editor',\n title: 'Editor',\n },\n ],\n }\n\n mockApi({\n apiVersion: TOKENS_API_VERSION,\n uri: '/projects/test-project/roles',\n }).reply(200, mockRoles)\n\n mockApi({\n apiVersion: TOKENS_API_VERSION,\n method: 'post',\n uri: '/projects/test-project/tokens',\n }).reply(200, mockToken)\n\n const {stdout} = await testCommand(AddTokenCommand, ['Editor Token', '--role=editor'], {\n mocks: defaultMocks,\n })\n\n expect(stdout).toContain('Token created successfully!')\n expect(stdout).toContain('Label: Editor Token')\n expect(stdout).toContain('Role: Editor')\n expect(stdout).toContain('Token: sk_test_editor1234')\n })\n\n test('outputs JSON when --json flag is used', async () => {\n const mockRoles = [\n {\n appliesToRobots: true,\n appliesToUsers: true,\n description: 'Can read documents',\n isCustom: false,\n name: 'viewer',\n projectId: 'test-project',\n title: 'Viewer',\n },\n ]\n\n const mockToken = {\n id: 'token-json',\n key: 'sk_test_json1234',\n label: 'JSON Token',\n projectUserId: 'user-123',\n roles: [\n {\n name: 'viewer',\n title: 'Viewer',\n },\n ],\n }\n\n mockApi({\n apiVersion: TOKENS_API_VERSION,\n uri: '/projects/test-project/roles',\n }).reply(200, mockRoles)\n\n mockApi({\n apiVersion: TOKENS_API_VERSION,\n method: 'post',\n uri: '/projects/test-project/tokens',\n }).reply(200, mockToken)\n\n const {stdout} = await testCommand(AddTokenCommand, ['JSON Token', '--json'], {\n mocks: defaultMocks,\n })\n\n const parsedOutput = JSON.parse(stdout)\n expect(parsedOutput).toEqual(mockToken)\n })\n\n test('works in unattended mode with --yes flag', async () => {\n const mockToken = {\n id: 'token-unattended',\n key: 'sk_test_unattended1234',\n label: 'Unattended Token',\n projectUserId: 'user-123',\n roles: [\n {\n name: 'viewer',\n title: 'Viewer',\n },\n ],\n }\n\n // Only mock the token creation API, not the roles API since unattended mode uses default role\n mockApi({\n apiVersion: TOKENS_API_VERSION,\n method: 'post',\n uri: '/projects/test-project/tokens',\n }).reply(200, mockToken)\n\n const {stdout} = await testCommand(AddTokenCommand, ['Unattended Token', '--yes'], {\n mocks: defaultMocks,\n })\n\n expect(stdout).toContain('Token created successfully!')\n expect(stdout).toContain('Label: Unattended Token')\n })\n\n test('handles invalid role error', async () => {\n const mockRoles = [\n {\n appliesToRobots: true,\n appliesToUsers: true,\n description: 'Can read documents',\n isCustom: false,\n name: 'viewer',\n projectId: 'test-project',\n title: 'Viewer',\n },\n ]\n\n mockApi({\n apiVersion: TOKENS_API_VERSION,\n uri: '/projects/test-project/roles',\n }).reply(200, mockRoles)\n\n const {error} = await testCommand(AddTokenCommand, ['Test Token', '--role=invalid'], {\n mocks: defaultMocks,\n })\n\n expect(error).toBeInstanceOf(Error)\n expect(error?.message).toContain('Invalid role \"invalid\"')\n expect(error?.message).toContain('Available roles: viewer')\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test('handles API error during token creation', async () => {\n const mockRoles = [\n {\n appliesToRobots: true,\n appliesToUsers: true,\n description: 'Can read documents',\n isCustom: false,\n name: 'viewer',\n projectId: 'test-project',\n title: 'Viewer',\n },\n ]\n\n mockApi({\n apiVersion: TOKENS_API_VERSION,\n uri: '/projects/test-project/roles',\n }).reply(200, mockRoles)\n\n mockApi({\n apiVersion: TOKENS_API_VERSION,\n method: 'post',\n uri: '/projects/test-project/tokens',\n }).reply(500, {message: 'Internal Server Error'})\n\n const {error} = await testCommand(AddTokenCommand, ['Failed Token'], {mocks: defaultMocks})\n\n expect(error).toBeInstanceOf(Error)\n expect(error?.message).toContain('Token creation failed')\n expect(error?.message).toContain('Internal Server Error')\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test('throws error when no project ID is found', async () => {\n const {error} = await testCommand(AddTokenCommand, ['Test Token'], {\n mocks: {\n ...defaultMocks,\n cliConfig: {api: {projectId: undefined}},\n },\n })\n\n expect(error).toBeInstanceOf(Error)\n expect(error?.message).toEqual(NO_PROJECT_ID)\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test('handles no roles available for tokens', async () => {\n const mockRoles = [\n {\n appliesToRobots: false, // Not applicable to robots\n appliesToUsers: true,\n description: 'Full access',\n isCustom: false,\n name: 'admin',\n projectId: 'test-project',\n title: 'Admin',\n },\n ]\n\n mockApi({\n apiVersion: TOKENS_API_VERSION,\n uri: '/projects/test-project/roles',\n }).reply(200, mockRoles)\n\n const {error} = await testCommand(AddTokenCommand, ['Test Token'], {mocks: defaultMocks})\n\n expect(error).toBeInstanceOf(Error)\n expect(error?.message).toContain('No roles available for tokens')\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test('prompts for label when not provided in interactive mode', async () => {\n const mockRoles = [\n {\n appliesToRobots: true,\n appliesToUsers: true,\n description: 'Can read documents',\n isCustom: false,\n name: 'viewer',\n projectId: 'test-project',\n title: 'Viewer',\n },\n ]\n\n const mockToken = {\n id: 'token-prompted',\n key: 'sk_test_prompted1234',\n label: 'Prompted Label',\n projectUserId: 'user-123',\n roles: [\n {\n name: 'viewer',\n title: 'Viewer',\n },\n ],\n }\n\n mockedInput.mockResolvedValueOnce('Prompted Label')\n mockedSelect.mockResolvedValueOnce('viewer')\n\n mockApi({\n apiVersion: TOKENS_API_VERSION,\n uri: '/projects/test-project/roles',\n }).reply(200, mockRoles)\n\n mockApi({\n apiVersion: TOKENS_API_VERSION,\n method: 'post',\n uri: '/projects/test-project/tokens',\n }).reply(200, mockToken)\n\n const {stdout} = await testCommand(AddTokenCommand, [], {mocks: defaultMocks})\n\n expect(mockedInput).toHaveBeenCalledWith({\n message: 'Token label:',\n validate: expect.any(Function),\n })\n expect(stdout).toContain('Token created successfully!')\n expect(stdout).toContain('Label: Prompted Label')\n })\n\n test('validates label input - rejects empty label', async () => {\n // Mock input to capture the validation function and return a valid label\n mockedInput.mockResolvedValueOnce('Valid Label')\n mockedSelect.mockResolvedValueOnce('viewer')\n\n const mockRoles = [\n {\n appliesToRobots: true,\n appliesToUsers: true,\n description: 'Can read documents',\n isCustom: false,\n name: 'viewer',\n projectId: 'test-project',\n title: 'Viewer',\n },\n ]\n\n const mockToken = {\n id: 'token-validated',\n key: 'sk_test_validated1234',\n label: 'Valid Label',\n projectUserId: 'user-123',\n roles: [\n {\n name: 'viewer',\n title: 'Viewer',\n },\n ],\n }\n\n mockApi({\n apiVersion: TOKENS_API_VERSION,\n uri: '/projects/test-project/roles',\n }).reply(200, mockRoles)\n\n mockApi({\n apiVersion: TOKENS_API_VERSION,\n method: 'post',\n uri: '/projects/test-project/tokens',\n }).reply(200, mockToken)\n\n await testCommand(AddTokenCommand, [], {mocks: defaultMocks})\n\n // Test that the validation function correctly rejects empty and whitespace-only strings\n const inputCall = mockedInput.mock.calls[0]\n expect(inputCall).toBeDefined()\n const options = inputCall[0]\n expect(options.validate).toBeDefined()\n\n if (options.validate) {\n expect(options.validate('')).toBe('Label cannot be empty')\n expect(options.validate(' ')).toBe('Label cannot be empty')\n expect(options.validate('Valid Label')).toBe(true)\n }\n })\n\n test('throws error when no label provided in non-interactive mode with --yes flag', async () => {\n const {error} = await testCommand(AddTokenCommand, ['--yes'], {mocks: defaultMocks})\n\n expect(error).toBeInstanceOf(Error)\n expect(error?.message).toContain('Token label is required in non-interactive mode')\n expect(error?.message).toContain('Provide a label as an argument')\n expect(error?.oclif?.exit).toBe(1)\n })\n})\n"],"names":["runCommand","input","select","mockApi","testCommand","nock","afterEach","describe","expect","test","vi","TOKENS_API_VERSION","NO_PROJECT_ID","AddTokenCommand","mock","actual","importActual","fn","mockedInput","mocked","mockedSelect","testProjectId","defaultMocks","cliConfig","api","projectId","isInteractive","projectRoot","directory","path","type","token","clearAllMocks","pending","pendingMocks","cleanAll","toEqual","stdout","toContain","mockRoles","appliesToRobots","appliesToUsers","description","isCustom","name","title","mockToken","id","key","label","projectUserId","roles","apiVersion","uri","reply","method","mocks","parsedOutput","JSON","parse","error","toBeInstanceOf","Error","message","oclif","exit","toBe","undefined","mockResolvedValueOnce","toHaveBeenCalledWith","validate","any","Function","inputCall","calls","toBeDefined","options"],"mappings":"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"}
@@ -57,29 +57,28 @@ const TEST_TOKENS = {
57
57
  ]
58
58
  })
59
59
  };
60
- // Mock the config functions with relative paths
61
- vi.mock('../../../../../cli-core/src/config/findProjectRoot.js', ()=>({
62
- findProjectRoot: vi.fn().mockResolvedValue({
63
- directory: '/test/path',
64
- root: '/test/path',
65
- type: 'studio'
66
- })
67
- }));
68
- vi.mock('../../../../../cli-core/src/config/cli/getCliConfig.js', ()=>({
69
- getCliConfig: vi.fn().mockResolvedValue({
70
- api: {
71
- projectId: 'test-project'
72
- }
73
- })
74
- }));
75
- vi.mock('../../../../../cli-core/src/services/getCliToken.js', ()=>({
76
- getCliToken: vi.fn().mockResolvedValue('test-token')
77
- }));
78
- // Mock inquirer prompts
79
- vi.mock('@sanity/cli-core/ux', ()=>({
60
+ const testProjectId = 'test-project';
61
+ const defaultMocks = {
62
+ cliConfig: {
63
+ api: {
64
+ projectId: testProjectId
65
+ }
66
+ },
67
+ projectRoot: {
68
+ directory: '/test/path',
69
+ path: '/test/path/sanity.config.ts',
70
+ type: 'studio'
71
+ },
72
+ token: 'test-token'
73
+ };
74
+ vi.mock('@sanity/cli-core/ux', async ()=>{
75
+ const actual = await vi.importActual('@sanity/cli-core/ux');
76
+ return {
77
+ ...actual,
80
78
  confirm: vi.fn(),
81
79
  select: vi.fn()
82
- }));
80
+ };
81
+ });
83
82
  describe('#tokens:delete', ()=>{
84
83
  afterEach(()=>{
85
84
  vi.clearAllMocks();
@@ -104,7 +103,9 @@ describe('#tokens:delete', ()=>{
104
103
  }).reply(204);
105
104
  const { stdout } = await testCommand(DeleteTokensCommand, [
106
105
  'token-api-123'
107
- ]);
106
+ ], {
107
+ mocks: defaultMocks
108
+ });
108
109
  expect(stdout).toBe('Token deleted successfully\n');
109
110
  expect(confirm).toHaveBeenCalledWith({
110
111
  default: false,
@@ -120,7 +121,9 @@ describe('#tokens:delete', ()=>{
120
121
  const { stdout } = await testCommand(DeleteTokensCommand, [
121
122
  'token-api-123',
122
123
  '--yes'
123
- ]);
124
+ ], {
125
+ mocks: defaultMocks
126
+ });
124
127
  expect(stdout).toBe('Token deleted successfully\n');
125
128
  });
126
129
  test('deletes a specific token by ID with -y flag (skips confirmation)', async ()=>{
@@ -132,7 +135,9 @@ describe('#tokens:delete', ()=>{
132
135
  const { stdout } = await testCommand(DeleteTokensCommand, [
133
136
  'token-api-123',
134
137
  '-y'
135
- ]);
138
+ ], {
139
+ mocks: defaultMocks
140
+ });
136
141
  expect(stdout).toBe('Token deleted successfully\n');
137
142
  });
138
143
  test('cancels deletion when user declines confirmation', async ()=>{
@@ -140,7 +145,9 @@ describe('#tokens:delete', ()=>{
140
145
  vi.mocked(confirm).mockResolvedValue(false);
141
146
  const { error } = await testCommand(DeleteTokensCommand, [
142
147
  'token-api-123'
143
- ]);
148
+ ], {
149
+ mocks: defaultMocks
150
+ });
144
151
  expect(error).toBeInstanceOf(Error);
145
152
  expect(error?.message).toContain('Operation cancelled');
146
153
  expect(error?.oclif?.exit).toBe(1);
@@ -161,7 +168,9 @@ describe('#tokens:delete', ()=>{
161
168
  method: 'delete',
162
169
  uri: '/projects/test-project/tokens/token-read-456'
163
170
  }).reply(204);
164
- const { stdout } = await testCommand(DeleteTokensCommand);
171
+ const { stdout } = await testCommand(DeleteTokensCommand, [], {
172
+ mocks: defaultMocks
173
+ });
165
174
  expect(stdout).toBe('Token deleted successfully\n');
166
175
  expect(select).toHaveBeenCalledWith({
167
176
  choices: [
@@ -206,7 +215,9 @@ describe('#tokens:delete', ()=>{
206
215
  method: 'delete',
207
216
  uri: '/projects/test-project/tokens/token-multi-123'
208
217
  }).reply(204);
209
- const { stdout } = await testCommand(DeleteTokensCommand);
218
+ const { stdout } = await testCommand(DeleteTokensCommand, [], {
219
+ mocks: defaultMocks
220
+ });
210
221
  expect(stdout).toBe('Token deleted successfully\n');
211
222
  expect(select).toHaveBeenCalledWith({
212
223
  choices: [
@@ -238,7 +249,9 @@ describe('#tokens:delete', ()=>{
238
249
  method: 'delete',
239
250
  uri: '/projects/test-project/tokens/token-no-role-123'
240
251
  }).reply(204);
241
- const { stdout } = await testCommand(DeleteTokensCommand);
252
+ const { stdout } = await testCommand(DeleteTokensCommand, [], {
253
+ mocks: defaultMocks
254
+ });
242
255
  expect(stdout).toBe('Token deleted successfully\n');
243
256
  expect(select).toHaveBeenCalledWith({
244
257
  choices: [
@@ -261,7 +274,9 @@ describe('#tokens:delete', ()=>{
261
274
  const { error } = await testCommand(DeleteTokensCommand, [
262
275
  'nonexistent-token',
263
276
  '--yes'
264
- ]);
277
+ ], {
278
+ mocks: defaultMocks
279
+ });
265
280
  expect(error).toBeInstanceOf(Error);
266
281
  expect(error?.message).toContain('Token with ID "nonexistent-token" not found');
267
282
  expect(error?.oclif?.exit).toBe(1);
@@ -271,7 +286,9 @@ describe('#tokens:delete', ()=>{
271
286
  apiVersion: TOKENS_API_VERSION,
272
287
  uri: '/projects/test-project/tokens'
273
288
  }).reply(200, []);
274
- const { error } = await testCommand(DeleteTokensCommand);
289
+ const { error } = await testCommand(DeleteTokensCommand, [], {
290
+ mocks: defaultMocks
291
+ });
275
292
  expect(error).toBeInstanceOf(Error);
276
293
  expect(error?.message).toContain('Token deletion failed');
277
294
  expect(error?.message).toContain('No tokens found');
@@ -299,7 +316,9 @@ describe('#tokens:delete', ()=>{
299
316
  const { error } = await testCommand(DeleteTokensCommand, [
300
317
  'token-api-123',
301
318
  '--yes'
302
- ]);
319
+ ], {
320
+ mocks: defaultMocks
321
+ });
303
322
  expect(error).toBeInstanceOf(Error);
304
323
  expect(error?.message).toContain('Token deletion failed');
305
324
  expect(error?.message).toContain(message);
@@ -312,7 +331,9 @@ describe('#tokens:delete', ()=>{
312
331
  }).reply(404, {
313
332
  message: 'Project not found'
314
333
  });
315
- const { error } = await testCommand(DeleteTokensCommand);
334
+ const { error } = await testCommand(DeleteTokensCommand, [], {
335
+ mocks: defaultMocks
336
+ });
316
337
  expect(error).toBeInstanceOf(Error);
317
338
  expect(error?.message).toContain('Token with ID "undefined" not found');
318
339
  expect(error?.oclif?.exit).toBe(1);
@@ -324,7 +345,9 @@ describe('#tokens:delete', ()=>{
324
345
  }).reply(500, {
325
346
  message: 'Internal Server Error'
326
347
  });
327
- const { error } = await testCommand(DeleteTokensCommand);
348
+ const { error } = await testCommand(DeleteTokensCommand, [], {
349
+ mocks: defaultMocks
350
+ });
328
351
  expect(error).toBeInstanceOf(Error);
329
352
  expect(error?.message).toContain('Token deletion failed');
330
353
  expect(error?.message).toContain('Internal Server Error');
@@ -340,22 +363,27 @@ describe('#tokens:delete', ()=>{
340
363
  projectId: ''
341
364
  }
342
365
  ])('throws error when $desc', async ({ projectId })=>{
343
- const { getCliConfig } = await import('../../../../../cli-core/src/config/cli/getCliConfig.js');
344
- vi.mocked(getCliConfig).mockResolvedValueOnce({
345
- api: {
346
- projectId
347
- }
348
- });
349
366
  const { error } = await testCommand(DeleteTokensCommand, [
350
367
  'token-api-123'
351
- ]);
368
+ ], {
369
+ mocks: {
370
+ ...defaultMocks,
371
+ cliConfig: {
372
+ api: {
373
+ projectId
374
+ }
375
+ }
376
+ }
377
+ });
352
378
  expect(error).toBeInstanceOf(Error);
353
379
  expect(error?.message).toEqual(NO_PROJECT_ID);
354
380
  expect(error?.oclif?.exit).toBe(1);
355
381
  });
356
382
  test('handles network errors when fetching tokens', async ()=>{
357
383
  // Don't set up any mock to simulate network failure
358
- const { error } = await testCommand(DeleteTokensCommand);
384
+ const { error } = await testCommand(DeleteTokensCommand, [], {
385
+ mocks: defaultMocks
386
+ });
359
387
  expect(error).toBeInstanceOf(Error);
360
388
  expect(error?.message).toContain('Token deletion failed');
361
389
  expect(error?.oclif?.exit).toBe(1);
@@ -365,7 +393,9 @@ describe('#tokens:delete', ()=>{
365
393
  const { error } = await testCommand(DeleteTokensCommand, [
366
394
  'token-api-123',
367
395
  '--yes'
368
- ]);
396
+ ], {
397
+ mocks: defaultMocks
398
+ });
369
399
  expect(error).toBeInstanceOf(Error);
370
400
  expect(error?.message).toContain('Token deletion failed');
371
401
  expect(error?.oclif?.exit).toBe(1);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/commands/tokens/__tests__/delete.test.ts"],"sourcesContent":["import {runCommand} from '@oclif/test'\nimport {mockApi, testCommand} from '@sanity/cli-test'\nimport nock from 'nock'\nimport {afterEach, describe, expect, test, vi} from 'vitest'\n\nimport {TOKENS_API_VERSION} from '../../../actions/tokens/constants.js'\nimport {type Token} from '../../../actions/tokens/types.js'\nimport {NO_PROJECT_ID} from '../../../util/errorMessages.js'\nimport {DeleteTokensCommand} from '../delete.js'\n\n// Test fixtures\nconst createToken = (overrides: Partial<Token> & {id: string}): Token => ({\n createdAt: '2023-01-01T00:00:00Z',\n createdBy: 'user-creator',\n label: 'Test Token',\n lastUsedAt: null,\n permissions: ['read', 'write'],\n projectId: 'test-project',\n projectUserId: 'user-123',\n roles: [{name: 'editor', title: 'Editor'}],\n ...overrides,\n})\n\nconst TEST_TOKENS = {\n API_TOKEN: createToken({\n id: 'token-api-123',\n label: 'API Token',\n roles: [{name: 'editor', title: 'Editor'}],\n }),\n READ_TOKEN: createToken({\n id: 'token-read-456',\n label: 'Read Token',\n roles: [{name: 'viewer', title: 'Viewer'}],\n }),\n WRITE_TOKEN: createToken({\n id: 'token-write-789',\n label: 'Write Token',\n roles: [{name: 'administrator', title: 'Administrator'}],\n }),\n} as const\n\n// Mock the config functions with relative paths\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\n// Mock inquirer prompts\nvi.mock('@sanity/cli-core/ux', () => ({\n confirm: vi.fn(),\n select: vi.fn(),\n}))\n\ndescribe('#tokens:delete', () => {\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(['tokens delete', '--help'])\n expect(stdout).toContain('Delete an API token from this project')\n })\n\n test('deletes a specific token by ID with confirmation', async () => {\n const {confirm} = await import('@sanity/cli-core/ux')\n vi.mocked(confirm).mockResolvedValue(true)\n\n mockApi({\n apiVersion: TOKENS_API_VERSION,\n method: 'delete',\n uri: '/projects/test-project/tokens/token-api-123',\n }).reply(204)\n\n const {stdout} = await testCommand(DeleteTokensCommand, ['token-api-123'])\n expect(stdout).toBe('Token deleted successfully\\n')\n expect(confirm).toHaveBeenCalledWith({\n default: false,\n message: 'Are you sure you want to delete the token with ID \"token-api-123\"?',\n })\n })\n\n test('deletes a specific token by ID with --yes flag (skips confirmation)', async () => {\n mockApi({\n apiVersion: TOKENS_API_VERSION,\n method: 'delete',\n uri: '/projects/test-project/tokens/token-api-123',\n }).reply(204)\n\n const {stdout} = await testCommand(DeleteTokensCommand, ['token-api-123', '--yes'])\n expect(stdout).toBe('Token deleted successfully\\n')\n })\n\n test('deletes a specific token by ID with -y flag (skips confirmation)', async () => {\n mockApi({\n apiVersion: TOKENS_API_VERSION,\n method: 'delete',\n uri: '/projects/test-project/tokens/token-api-123',\n }).reply(204)\n\n const {stdout} = await testCommand(DeleteTokensCommand, ['token-api-123', '-y'])\n expect(stdout).toBe('Token deleted successfully\\n')\n })\n\n test('cancels deletion when user declines confirmation', async () => {\n const {confirm} = await import('@sanity/cli-core/ux')\n vi.mocked(confirm).mockResolvedValue(false)\n\n const {error} = await testCommand(DeleteTokensCommand, ['token-api-123'])\n expect(error).toBeInstanceOf(Error)\n expect(error?.message).toContain('Operation cancelled')\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test('prompts user to select token when none specified', async () => {\n const {confirm, select} = await import('@sanity/cli-core/ux')\n vi.mocked(select).mockResolvedValue('token-read-456')\n vi.mocked(confirm).mockResolvedValue(true)\n\n mockApi({\n apiVersion: TOKENS_API_VERSION,\n uri: '/projects/test-project/tokens',\n }).reply(200, [TEST_TOKENS.API_TOKEN, TEST_TOKENS.READ_TOKEN])\n\n mockApi({\n apiVersion: TOKENS_API_VERSION,\n method: 'delete',\n uri: '/projects/test-project/tokens/token-read-456',\n }).reply(204)\n\n const {stdout} = await testCommand(DeleteTokensCommand)\n expect(stdout).toBe('Token deleted successfully\\n')\n expect(select).toHaveBeenCalledWith({\n choices: [\n {name: 'API Token (Editor)', value: 'token-api-123'},\n {name: 'Read Token (Viewer)', value: 'token-read-456'},\n ],\n message: 'Select token to delete:',\n })\n })\n\n test('handles tokens with multiple roles', async () => {\n const {confirm, select} = await import('@sanity/cli-core/ux')\n const multiRoleToken = createToken({\n id: 'token-multi-123',\n label: 'Multi Role Token',\n roles: [\n {name: 'editor', title: 'Editor'},\n {name: 'viewer', title: 'Viewer'},\n ],\n })\n vi.mocked(select).mockResolvedValue('token-multi-123')\n vi.mocked(confirm).mockResolvedValue(true)\n\n mockApi({\n apiVersion: TOKENS_API_VERSION,\n uri: '/projects/test-project/tokens',\n }).reply(200, [multiRoleToken])\n\n mockApi({\n apiVersion: TOKENS_API_VERSION,\n method: 'delete',\n uri: '/projects/test-project/tokens/token-multi-123',\n }).reply(204)\n\n const {stdout} = await testCommand(DeleteTokensCommand)\n expect(stdout).toBe('Token deleted successfully\\n')\n expect(select).toHaveBeenCalledWith({\n choices: [{name: 'Multi Role Token (Editor, Viewer)', value: 'token-multi-123'}],\n message: 'Select token to delete:',\n })\n })\n\n test('handles tokens with no roles', async () => {\n const {confirm, select} = await import('@sanity/cli-core/ux')\n const noRoleToken = createToken({\n id: 'token-no-role-123',\n label: 'No Role Token',\n roles: [],\n })\n vi.mocked(select).mockResolvedValue('token-no-role-123')\n vi.mocked(confirm).mockResolvedValue(true)\n\n mockApi({\n apiVersion: TOKENS_API_VERSION,\n uri: '/projects/test-project/tokens',\n }).reply(200, [noRoleToken])\n\n mockApi({\n apiVersion: TOKENS_API_VERSION,\n method: 'delete',\n uri: '/projects/test-project/tokens/token-no-role-123',\n }).reply(204)\n\n const {stdout} = await testCommand(DeleteTokensCommand)\n expect(stdout).toBe('Token deleted successfully\\n')\n expect(select).toHaveBeenCalledWith({\n choices: [{name: 'No Role Token ()', value: 'token-no-role-123'}],\n message: 'Select token to delete:',\n })\n })\n\n test('throws error when token not found (404)', async () => {\n mockApi({\n apiVersion: TOKENS_API_VERSION,\n method: 'delete',\n uri: '/projects/test-project/tokens/nonexistent-token',\n }).reply(404, {message: 'Token not found'})\n\n const {error} = await testCommand(DeleteTokensCommand, ['nonexistent-token', '--yes'])\n expect(error).toBeInstanceOf(Error)\n expect(error?.message).toContain('Token with ID \"nonexistent-token\" not found')\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test('throws error when no tokens exist in project', async () => {\n mockApi({\n apiVersion: TOKENS_API_VERSION,\n uri: '/projects/test-project/tokens',\n }).reply(200, [])\n\n const {error} = await testCommand(DeleteTokensCommand)\n expect(error).toBeInstanceOf(Error)\n expect(error?.message).toContain('Token deletion failed')\n expect(error?.message).toContain('No tokens found')\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test.each([\n {desc: 'when deleting token', message: 'Internal Server Error', statusCode: 500},\n {desc: 'with forbidden error when deleting token', message: 'Forbidden', statusCode: 403},\n ])('handles API error $desc', async ({message, statusCode}) => {\n mockApi({\n apiVersion: TOKENS_API_VERSION,\n method: 'delete',\n uri: '/projects/test-project/tokens/token-api-123',\n }).reply(statusCode, {message})\n\n const {error} = await testCommand(DeleteTokensCommand, ['token-api-123', '--yes'])\n expect(error).toBeInstanceOf(Error)\n expect(error?.message).toContain('Token deletion failed')\n expect(error?.message).toContain(message)\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test('handles API error when fetching tokens', async () => {\n mockApi({\n apiVersion: TOKENS_API_VERSION,\n uri: '/projects/test-project/tokens',\n }).reply(404, {message: 'Project not found'})\n\n const {error} = await testCommand(DeleteTokensCommand)\n expect(error).toBeInstanceOf(Error)\n expect(error?.message).toContain('Token with ID \"undefined\" not found')\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test('handles API error with server error when fetching tokens', async () => {\n mockApi({\n apiVersion: TOKENS_API_VERSION,\n uri: '/projects/test-project/tokens',\n }).reply(500, {message: 'Internal Server Error'})\n\n const {error} = await testCommand(DeleteTokensCommand)\n expect(error).toBeInstanceOf(Error)\n expect(error?.message).toContain('Token deletion failed')\n expect(error?.message).toContain('Internal Server Error')\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test.each([\n {desc: 'no project ID is found', projectId: undefined},\n {desc: 'project ID is empty string', projectId: ''},\n ])('throws error when $desc', async ({projectId}) => {\n const {getCliConfig} = await import('../../../../../cli-core/src/config/cli/getCliConfig.js')\n vi.mocked(getCliConfig).mockResolvedValueOnce({\n api: {projectId},\n })\n\n const {error} = await testCommand(DeleteTokensCommand, ['token-api-123'])\n expect(error).toBeInstanceOf(Error)\n expect(error?.message).toEqual(NO_PROJECT_ID)\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test('handles network errors when fetching tokens', async () => {\n // Don't set up any mock to simulate network failure\n const {error} = await testCommand(DeleteTokensCommand)\n expect(error).toBeInstanceOf(Error)\n expect(error?.message).toContain('Token deletion failed')\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test('handles network errors when deleting token', async () => {\n // Don't set up any mock to simulate network failure\n const {error} = await testCommand(DeleteTokensCommand, ['token-api-123', '--yes'])\n expect(error).toBeInstanceOf(Error)\n expect(error?.message).toContain('Token deletion failed')\n expect(error?.oclif?.exit).toBe(1)\n })\n})\n"],"names":["runCommand","mockApi","testCommand","nock","afterEach","describe","expect","test","vi","TOKENS_API_VERSION","NO_PROJECT_ID","DeleteTokensCommand","createToken","overrides","createdAt","createdBy","label","lastUsedAt","permissions","projectId","projectUserId","roles","name","title","TEST_TOKENS","API_TOKEN","id","READ_TOKEN","WRITE_TOKEN","mock","findProjectRoot","fn","mockResolvedValue","directory","root","type","getCliConfig","api","getCliToken","confirm","select","clearAllMocks","pending","pendingMocks","cleanAll","toEqual","stdout","toContain","mocked","apiVersion","method","uri","reply","toBe","toHaveBeenCalledWith","default","message","error","toBeInstanceOf","Error","oclif","exit","choices","value","multiRoleToken","noRoleToken","each","desc","statusCode","undefined","mockResolvedValueOnce"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../src/commands/tokens/__tests__/delete.test.ts"],"sourcesContent":["import {runCommand} from '@oclif/test'\nimport {mockApi, testCommand} from '@sanity/cli-test'\nimport nock from 'nock'\nimport {afterEach, describe, expect, test, vi} from 'vitest'\n\nimport {TOKENS_API_VERSION} from '../../../actions/tokens/constants.js'\nimport {type Token} from '../../../actions/tokens/types.js'\nimport {NO_PROJECT_ID} from '../../../util/errorMessages.js'\nimport {DeleteTokensCommand} from '../delete.js'\n\n// Test fixtures\nconst createToken = (overrides: Partial<Token> & {id: string}): Token => ({\n createdAt: '2023-01-01T00:00:00Z',\n createdBy: 'user-creator',\n label: 'Test Token',\n lastUsedAt: null,\n permissions: ['read', 'write'],\n projectId: 'test-project',\n projectUserId: 'user-123',\n roles: [{name: 'editor', title: 'Editor'}],\n ...overrides,\n})\n\nconst TEST_TOKENS = {\n API_TOKEN: createToken({\n id: 'token-api-123',\n label: 'API Token',\n roles: [{name: 'editor', title: 'Editor'}],\n }),\n READ_TOKEN: createToken({\n id: 'token-read-456',\n label: 'Read Token',\n roles: [{name: 'viewer', title: 'Viewer'}],\n }),\n WRITE_TOKEN: createToken({\n id: 'token-write-789',\n label: 'Write Token',\n roles: [{name: 'administrator', title: 'Administrator'}],\n }),\n} as const\n\nconst testProjectId = 'test-project'\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: '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 confirm: vi.fn(),\n select: vi.fn(),\n }\n})\n\ndescribe('#tokens:delete', () => {\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(['tokens delete', '--help'])\n expect(stdout).toContain('Delete an API token from this project')\n })\n\n test('deletes a specific token by ID with confirmation', async () => {\n const {confirm} = await import('@sanity/cli-core/ux')\n vi.mocked(confirm).mockResolvedValue(true)\n\n mockApi({\n apiVersion: TOKENS_API_VERSION,\n method: 'delete',\n uri: '/projects/test-project/tokens/token-api-123',\n }).reply(204)\n\n const {stdout} = await testCommand(DeleteTokensCommand, ['token-api-123'], {mocks: defaultMocks})\n expect(stdout).toBe('Token deleted successfully\\n')\n expect(confirm).toHaveBeenCalledWith({\n default: false,\n message: 'Are you sure you want to delete the token with ID \"token-api-123\"?',\n })\n })\n\n test('deletes a specific token by ID with --yes flag (skips confirmation)', async () => {\n mockApi({\n apiVersion: TOKENS_API_VERSION,\n method: 'delete',\n uri: '/projects/test-project/tokens/token-api-123',\n }).reply(204)\n\n const {stdout} = await testCommand(DeleteTokensCommand, ['token-api-123', '--yes'], {mocks: defaultMocks})\n expect(stdout).toBe('Token deleted successfully\\n')\n })\n\n test('deletes a specific token by ID with -y flag (skips confirmation)', async () => {\n mockApi({\n apiVersion: TOKENS_API_VERSION,\n method: 'delete',\n uri: '/projects/test-project/tokens/token-api-123',\n }).reply(204)\n\n const {stdout} = await testCommand(DeleteTokensCommand, ['token-api-123', '-y'], {mocks: defaultMocks})\n expect(stdout).toBe('Token deleted successfully\\n')\n })\n\n test('cancels deletion when user declines confirmation', async () => {\n const {confirm} = await import('@sanity/cli-core/ux')\n vi.mocked(confirm).mockResolvedValue(false)\n\n const {error} = await testCommand(DeleteTokensCommand, ['token-api-123'], {mocks: defaultMocks})\n expect(error).toBeInstanceOf(Error)\n expect(error?.message).toContain('Operation cancelled')\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test('prompts user to select token when none specified', async () => {\n const {confirm, select} = await import('@sanity/cli-core/ux')\n vi.mocked(select).mockResolvedValue('token-read-456')\n vi.mocked(confirm).mockResolvedValue(true)\n\n mockApi({\n apiVersion: TOKENS_API_VERSION,\n uri: '/projects/test-project/tokens',\n }).reply(200, [TEST_TOKENS.API_TOKEN, TEST_TOKENS.READ_TOKEN])\n\n mockApi({\n apiVersion: TOKENS_API_VERSION,\n method: 'delete',\n uri: '/projects/test-project/tokens/token-read-456',\n }).reply(204)\n\n const {stdout} = await testCommand(DeleteTokensCommand, [], {mocks: defaultMocks})\n expect(stdout).toBe('Token deleted successfully\\n')\n expect(select).toHaveBeenCalledWith({\n choices: [\n {name: 'API Token (Editor)', value: 'token-api-123'},\n {name: 'Read Token (Viewer)', value: 'token-read-456'},\n ],\n message: 'Select token to delete:',\n })\n })\n\n test('handles tokens with multiple roles', async () => {\n const {confirm, select} = await import('@sanity/cli-core/ux')\n const multiRoleToken = createToken({\n id: 'token-multi-123',\n label: 'Multi Role Token',\n roles: [\n {name: 'editor', title: 'Editor'},\n {name: 'viewer', title: 'Viewer'},\n ],\n })\n vi.mocked(select).mockResolvedValue('token-multi-123')\n vi.mocked(confirm).mockResolvedValue(true)\n\n mockApi({\n apiVersion: TOKENS_API_VERSION,\n uri: '/projects/test-project/tokens',\n }).reply(200, [multiRoleToken])\n\n mockApi({\n apiVersion: TOKENS_API_VERSION,\n method: 'delete',\n uri: '/projects/test-project/tokens/token-multi-123',\n }).reply(204)\n\n const {stdout} = await testCommand(DeleteTokensCommand, [], {mocks: defaultMocks})\n expect(stdout).toBe('Token deleted successfully\\n')\n expect(select).toHaveBeenCalledWith({\n choices: [{name: 'Multi Role Token (Editor, Viewer)', value: 'token-multi-123'}],\n message: 'Select token to delete:',\n })\n })\n\n test('handles tokens with no roles', async () => {\n const {confirm, select} = await import('@sanity/cli-core/ux')\n const noRoleToken = createToken({\n id: 'token-no-role-123',\n label: 'No Role Token',\n roles: [],\n })\n vi.mocked(select).mockResolvedValue('token-no-role-123')\n vi.mocked(confirm).mockResolvedValue(true)\n\n mockApi({\n apiVersion: TOKENS_API_VERSION,\n uri: '/projects/test-project/tokens',\n }).reply(200, [noRoleToken])\n\n mockApi({\n apiVersion: TOKENS_API_VERSION,\n method: 'delete',\n uri: '/projects/test-project/tokens/token-no-role-123',\n }).reply(204)\n\n const {stdout} = await testCommand(DeleteTokensCommand, [], {mocks: defaultMocks})\n expect(stdout).toBe('Token deleted successfully\\n')\n expect(select).toHaveBeenCalledWith({\n choices: [{name: 'No Role Token ()', value: 'token-no-role-123'}],\n message: 'Select token to delete:',\n })\n })\n\n test('throws error when token not found (404)', async () => {\n mockApi({\n apiVersion: TOKENS_API_VERSION,\n method: 'delete',\n uri: '/projects/test-project/tokens/nonexistent-token',\n }).reply(404, {message: 'Token not found'})\n\n const {error} = await testCommand(DeleteTokensCommand, ['nonexistent-token', '--yes'], {mocks: defaultMocks})\n expect(error).toBeInstanceOf(Error)\n expect(error?.message).toContain('Token with ID \"nonexistent-token\" not found')\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test('throws error when no tokens exist in project', async () => {\n mockApi({\n apiVersion: TOKENS_API_VERSION,\n uri: '/projects/test-project/tokens',\n }).reply(200, [])\n\n const {error} = await testCommand(DeleteTokensCommand, [], {mocks: defaultMocks})\n expect(error).toBeInstanceOf(Error)\n expect(error?.message).toContain('Token deletion failed')\n expect(error?.message).toContain('No tokens found')\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test.each([\n {desc: 'when deleting token', message: 'Internal Server Error', statusCode: 500},\n {desc: 'with forbidden error when deleting token', message: 'Forbidden', statusCode: 403},\n ])('handles API error $desc', async ({message, statusCode}) => {\n mockApi({\n apiVersion: TOKENS_API_VERSION,\n method: 'delete',\n uri: '/projects/test-project/tokens/token-api-123',\n }).reply(statusCode, {message})\n\n const {error} = await testCommand(DeleteTokensCommand, ['token-api-123', '--yes'], {mocks: defaultMocks})\n expect(error).toBeInstanceOf(Error)\n expect(error?.message).toContain('Token deletion failed')\n expect(error?.message).toContain(message)\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test('handles API error when fetching tokens', async () => {\n mockApi({\n apiVersion: TOKENS_API_VERSION,\n uri: '/projects/test-project/tokens',\n }).reply(404, {message: 'Project not found'})\n\n const {error} = await testCommand(DeleteTokensCommand, [], {mocks: defaultMocks})\n expect(error).toBeInstanceOf(Error)\n expect(error?.message).toContain('Token with ID \"undefined\" not found')\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test('handles API error with server error when fetching tokens', async () => {\n mockApi({\n apiVersion: TOKENS_API_VERSION,\n uri: '/projects/test-project/tokens',\n }).reply(500, {message: 'Internal Server Error'})\n\n const {error} = await testCommand(DeleteTokensCommand, [], {mocks: defaultMocks})\n expect(error).toBeInstanceOf(Error)\n expect(error?.message).toContain('Token deletion failed')\n expect(error?.message).toContain('Internal Server Error')\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test.each([\n {desc: 'no project ID is found', projectId: undefined},\n {desc: 'project ID is empty string', projectId: ''},\n ])('throws error when $desc', async ({projectId}) => {\n const {error} = await testCommand(DeleteTokensCommand, ['token-api-123'], {\n mocks: {\n ...defaultMocks,\n cliConfig: {api: {projectId}},\n },\n })\n expect(error).toBeInstanceOf(Error)\n expect(error?.message).toEqual(NO_PROJECT_ID)\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test('handles network errors when fetching tokens', async () => {\n // Don't set up any mock to simulate network failure\n const {error} = await testCommand(DeleteTokensCommand, [], {mocks: defaultMocks})\n expect(error).toBeInstanceOf(Error)\n expect(error?.message).toContain('Token deletion failed')\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test('handles network errors when deleting token', async () => {\n // Don't set up any mock to simulate network failure\n const {error} = await testCommand(DeleteTokensCommand, ['token-api-123', '--yes'], {mocks: defaultMocks})\n expect(error).toBeInstanceOf(Error)\n expect(error?.message).toContain('Token deletion failed')\n expect(error?.oclif?.exit).toBe(1)\n })\n})\n"],"names":["runCommand","mockApi","testCommand","nock","afterEach","describe","expect","test","vi","TOKENS_API_VERSION","NO_PROJECT_ID","DeleteTokensCommand","createToken","overrides","createdAt","createdBy","label","lastUsedAt","permissions","projectId","projectUserId","roles","name","title","TEST_TOKENS","API_TOKEN","id","READ_TOKEN","WRITE_TOKEN","testProjectId","defaultMocks","cliConfig","api","projectRoot","directory","path","type","token","mock","actual","importActual","confirm","fn","select","clearAllMocks","pending","pendingMocks","cleanAll","toEqual","stdout","toContain","mocked","mockResolvedValue","apiVersion","method","uri","reply","mocks","toBe","toHaveBeenCalledWith","default","message","error","toBeInstanceOf","Error","oclif","exit","choices","value","multiRoleToken","noRoleToken","each","desc","statusCode","undefined"],"mappings":"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"}