@sentry/wizard 6.9.0 → 6.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (170) hide show
  1. package/CHANGELOG.md +56 -1
  2. package/dist/ci-ensure-runtime-loaded.sh +82 -0
  3. package/dist/e2e-tests/tests/angular-17.test.js +72 -82
  4. package/dist/e2e-tests/tests/angular-17.test.js.map +1 -1
  5. package/dist/e2e-tests/tests/angular-19.test.js +71 -80
  6. package/dist/e2e-tests/tests/angular-19.test.js.map +1 -1
  7. package/dist/e2e-tests/tests/cloudflare-worker.test.d.ts +1 -0
  8. package/dist/e2e-tests/tests/cloudflare-worker.test.js +64 -0
  9. package/dist/e2e-tests/tests/cloudflare-worker.test.js.map +1 -0
  10. package/dist/e2e-tests/tests/cloudflare-wrangler-sourcemaps.test.js +2 -5
  11. package/dist/e2e-tests/tests/cloudflare-wrangler-sourcemaps.test.js.map +1 -1
  12. package/dist/e2e-tests/tests/expo.test.js +36 -61
  13. package/dist/e2e-tests/tests/expo.test.js.map +1 -1
  14. package/dist/e2e-tests/tests/flutter.test.js +63 -70
  15. package/dist/e2e-tests/tests/flutter.test.js.map +1 -1
  16. package/dist/e2e-tests/tests/help-message.test.js +2 -2
  17. package/dist/e2e-tests/tests/help-message.test.js.map +1 -1
  18. package/dist/e2e-tests/tests/nextjs-14.test.js +54 -82
  19. package/dist/e2e-tests/tests/nextjs-14.test.js.map +1 -1
  20. package/dist/e2e-tests/tests/nextjs-15.test.js +95 -105
  21. package/dist/e2e-tests/tests/nextjs-15.test.js.map +1 -1
  22. package/dist/e2e-tests/tests/nextjs-16.test.d.ts +1 -0
  23. package/dist/e2e-tests/tests/nextjs-16.test.js +123 -0
  24. package/dist/e2e-tests/tests/nextjs-16.test.js.map +1 -0
  25. package/dist/e2e-tests/tests/nuxt-3.test.js +45 -58
  26. package/dist/e2e-tests/tests/nuxt-3.test.js.map +1 -1
  27. package/dist/e2e-tests/tests/nuxt-4.test.js +59 -73
  28. package/dist/e2e-tests/tests/nuxt-4.test.js.map +1 -1
  29. package/dist/e2e-tests/tests/pnpm-workspace.test.js +4 -7
  30. package/dist/e2e-tests/tests/pnpm-workspace.test.js.map +1 -1
  31. package/dist/e2e-tests/tests/react-native.test.js +44 -80
  32. package/dist/e2e-tests/tests/react-native.test.js.map +1 -1
  33. package/dist/e2e-tests/tests/react-router.test.js +163 -145
  34. package/dist/e2e-tests/tests/react-router.test.js.map +1 -1
  35. package/dist/e2e-tests/tests/remix.test.js +162 -132
  36. package/dist/e2e-tests/tests/remix.test.js.map +1 -1
  37. package/dist/e2e-tests/tests/sveltekit-hooks.test.js +48 -36
  38. package/dist/e2e-tests/tests/sveltekit-hooks.test.js.map +1 -1
  39. package/dist/e2e-tests/tests/sveltekit-tracing.test.js +3 -6
  40. package/dist/e2e-tests/tests/sveltekit-tracing.test.js.map +1 -1
  41. package/dist/e2e-tests/utils/index.d.ts +21 -43
  42. package/dist/e2e-tests/utils/index.js +108 -183
  43. package/dist/e2e-tests/utils/index.js.map +1 -1
  44. package/dist/get-e2e-test-matrix.mjs +11 -0
  45. package/dist/lib/Constants.d.ts +1 -0
  46. package/dist/lib/Constants.js +5 -0
  47. package/dist/lib/Constants.js.map +1 -1
  48. package/dist/src/android/android-wizard.js +2 -4
  49. package/dist/src/android/android-wizard.js.map +1 -1
  50. package/dist/src/angular/angular-wizard.js +4 -6
  51. package/dist/src/angular/angular-wizard.js.map +1 -1
  52. package/dist/src/angular/sdk-setup.js +1 -1
  53. package/dist/src/angular/sdk-setup.js.map +1 -1
  54. package/dist/src/apple/apple-wizard.js +2 -4
  55. package/dist/src/apple/apple-wizard.js.map +1 -1
  56. package/dist/src/cloudflare/cloudflare-wizard.d.ts +3 -0
  57. package/dist/src/cloudflare/cloudflare-wizard.js +99 -0
  58. package/dist/src/cloudflare/cloudflare-wizard.js.map +1 -0
  59. package/dist/src/cloudflare/sdk-setup.d.ts +7 -0
  60. package/dist/src/cloudflare/sdk-setup.js +47 -0
  61. package/dist/src/cloudflare/sdk-setup.js.map +1 -0
  62. package/dist/src/cloudflare/templates.d.ts +4 -0
  63. package/dist/src/cloudflare/templates.js +44 -0
  64. package/dist/src/cloudflare/templates.js.map +1 -0
  65. package/dist/src/cloudflare/wrangler/create-wrangler-config.d.ts +4 -0
  66. package/dist/src/cloudflare/wrangler/create-wrangler-config.js +27 -0
  67. package/dist/src/cloudflare/wrangler/create-wrangler-config.js.map +1 -0
  68. package/dist/src/cloudflare/wrangler/ensure-wrangler-config.d.ts +4 -0
  69. package/dist/src/cloudflare/wrangler/ensure-wrangler-config.js +25 -0
  70. package/dist/src/cloudflare/wrangler/ensure-wrangler-config.js.map +1 -0
  71. package/dist/src/cloudflare/wrangler/find-wrangler-config.d.ts +4 -0
  72. package/dist/src/cloudflare/wrangler/find-wrangler-config.js +23 -0
  73. package/dist/src/cloudflare/wrangler/find-wrangler-config.js.map +1 -0
  74. package/dist/src/cloudflare/wrangler/get-entry-point-from-wrangler-config.d.ts +6 -0
  75. package/dist/src/cloudflare/wrangler/get-entry-point-from-wrangler-config.js +52 -0
  76. package/dist/src/cloudflare/wrangler/get-entry-point-from-wrangler-config.js.map +1 -0
  77. package/dist/src/cloudflare/wrangler/update-wrangler-config.d.ts +17 -0
  78. package/dist/src/cloudflare/wrangler/update-wrangler-config.js +173 -0
  79. package/dist/src/cloudflare/wrangler/update-wrangler-config.js.map +1 -0
  80. package/dist/src/cloudflare/wrap-worker.d.ts +32 -0
  81. package/dist/src/cloudflare/wrap-worker.js +109 -0
  82. package/dist/src/cloudflare/wrap-worker.js.map +1 -0
  83. package/dist/src/flutter/flutter-wizard.js +3 -6
  84. package/dist/src/flutter/flutter-wizard.js.map +1 -1
  85. package/dist/src/nextjs/nextjs-wizard.js +46 -10
  86. package/dist/src/nextjs/nextjs-wizard.js.map +1 -1
  87. package/dist/src/nextjs/templates.d.ts +6 -3
  88. package/dist/src/nextjs/templates.js +144 -93
  89. package/dist/src/nextjs/templates.js.map +1 -1
  90. package/dist/src/nuxt/nuxt-wizard.js +3 -5
  91. package/dist/src/nuxt/nuxt-wizard.js.map +1 -1
  92. package/dist/src/react-native/react-native-wizard.js +2 -4
  93. package/dist/src/react-native/react-native-wizard.js.map +1 -1
  94. package/dist/src/react-router/codemods/client.entry.js +4 -1
  95. package/dist/src/react-router/codemods/client.entry.js.map +1 -1
  96. package/dist/src/react-router/react-router-wizard.js +3 -5
  97. package/dist/src/react-router/react-router-wizard.js.map +1 -1
  98. package/dist/src/react-router/sdk-example.js +5 -2
  99. package/dist/src/react-router/sdk-example.js.map +1 -1
  100. package/dist/src/react-router/sdk-setup.d.ts +1 -1
  101. package/dist/src/react-router/sdk-setup.js +3 -4
  102. package/dist/src/react-router/sdk-setup.js.map +1 -1
  103. package/dist/src/remix/remix-wizard.js +2 -4
  104. package/dist/src/remix/remix-wizard.js.map +1 -1
  105. package/dist/src/run.d.ts +1 -1
  106. package/dist/src/run.js +5 -0
  107. package/dist/src/run.js.map +1 -1
  108. package/dist/src/sourcemaps/tools/sentry-cli.js +1 -1
  109. package/dist/src/sourcemaps/tools/sentry-cli.js.map +1 -1
  110. package/dist/src/sourcemaps/tools/wrangler.js +1 -1
  111. package/dist/src/sourcemaps/tools/wrangler.js.map +1 -1
  112. package/dist/src/sveltekit/sveltekit-wizard.js +4 -6
  113. package/dist/src/sveltekit/sveltekit-wizard.js.map +1 -1
  114. package/dist/src/telemetry.d.ts +1 -1
  115. package/dist/src/telemetry.js +52 -31
  116. package/dist/src/telemetry.js.map +1 -1
  117. package/dist/src/utils/abort-if-sportlight-not-supported.d.ts +5 -0
  118. package/dist/src/utils/abort-if-sportlight-not-supported.js +40 -0
  119. package/dist/src/utils/abort-if-sportlight-not-supported.js.map +1 -0
  120. package/dist/src/utils/ast-utils.d.ts +1 -1
  121. package/dist/src/utils/ast-utils.js.map +1 -1
  122. package/dist/src/utils/clack/index.d.ts +19 -2
  123. package/dist/src/utils/clack/index.js +174 -12
  124. package/dist/src/utils/clack/index.js.map +1 -1
  125. package/dist/src/utils/clack/mcp-config.js +117 -59
  126. package/dist/src/utils/clack/mcp-config.js.map +1 -1
  127. package/dist/src/version.d.ts +1 -1
  128. package/dist/src/version.js +1 -1
  129. package/dist/src/version.js.map +1 -1
  130. package/dist/test/angular/angular-wizard.test.js +2 -4
  131. package/dist/test/angular/angular-wizard.test.js.map +1 -1
  132. package/dist/test/apple/cocoapod.test.js +7 -3
  133. package/dist/test/apple/cocoapod.test.js.map +1 -1
  134. package/dist/test/apple/code-tools.test.js +8 -2
  135. package/dist/test/apple/code-tools.test.js.map +1 -1
  136. package/dist/test/cloudflare/create-wrangler-config.test.d.ts +1 -0
  137. package/dist/test/cloudflare/create-wrangler-config.test.js +48 -0
  138. package/dist/test/cloudflare/create-wrangler-config.test.js.map +1 -0
  139. package/dist/test/cloudflare/ensure-wrangler-config.test.d.ts +1 -0
  140. package/dist/test/cloudflare/ensure-wrangler-config.test.js +61 -0
  141. package/dist/test/cloudflare/ensure-wrangler-config.test.js.map +1 -0
  142. package/dist/test/cloudflare/find-wrangler-config.test.d.ts +1 -0
  143. package/dist/test/cloudflare/find-wrangler-config.test.js +77 -0
  144. package/dist/test/cloudflare/find-wrangler-config.test.js.map +1 -0
  145. package/dist/test/cloudflare/get-entry-point-from-wrangler-config.test.d.ts +1 -0
  146. package/dist/test/cloudflare/get-entry-point-from-wrangler-config.test.js +81 -0
  147. package/dist/test/cloudflare/get-entry-point-from-wrangler-config.test.js.map +1 -0
  148. package/dist/test/cloudflare/sdk-setup.test.d.ts +1 -0
  149. package/dist/test/cloudflare/sdk-setup.test.js +152 -0
  150. package/dist/test/cloudflare/sdk-setup.test.js.map +1 -0
  151. package/dist/test/cloudflare/templates.test.d.ts +1 -0
  152. package/dist/test/cloudflare/templates.test.js +68 -0
  153. package/dist/test/cloudflare/templates.test.js.map +1 -0
  154. package/dist/test/cloudflare/update-wrangler-config.test.d.ts +1 -0
  155. package/dist/test/cloudflare/update-wrangler-config.test.js +216 -0
  156. package/dist/test/cloudflare/update-wrangler-config.test.js.map +1 -0
  157. package/dist/test/cloudflare/wrap-worker.test.d.ts +1 -0
  158. package/dist/test/cloudflare/wrap-worker.test.js +143 -0
  159. package/dist/test/cloudflare/wrap-worker.test.js.map +1 -0
  160. package/dist/test/nextjs/templates.test.js +156 -87
  161. package/dist/test/nextjs/templates.test.js.map +1 -1
  162. package/dist/test/nextjs/wizard-double-wrap-prevention.test.js +12 -7
  163. package/dist/test/nextjs/wizard-double-wrap-prevention.test.js.map +1 -1
  164. package/dist/test/react-router/sdk-setup.test.js +2 -2
  165. package/dist/test/react-router/sdk-setup.test.js.map +1 -1
  166. package/dist/test/utils/clack/index.test.js +37 -29
  167. package/dist/test/utils/clack/index.test.js.map +1 -1
  168. package/dist/test/utils/clack/mcp-config.test.js +176 -51
  169. package/dist/test/utils/clack/mcp-config.test.js.map +1 -1
  170. package/package.json +6 -5
@@ -64,6 +64,28 @@ const mockedAxios = axios_1.default;
64
64
  vitest_1.vi.mock('opn', () => ({
65
65
  default: vitest_1.vi.fn(() => Promise.resolve({ on: vitest_1.vi.fn() })),
66
66
  }));
67
+ // Sentry mock functions defined at module level for the abort tests
68
+ const mockRootSpan = {
69
+ setStatus: vitest_1.vi.fn(),
70
+ end: vitest_1.vi.fn(),
71
+ };
72
+ const mockActiveSpan = {};
73
+ let mockSentrySession = { status: 999 };
74
+ vitest_1.vi.mock('@sentry/node', async () => {
75
+ const actual = await vitest_1.vi.importActual('@sentry/node');
76
+ return {
77
+ ...actual,
78
+ getActiveSpan: vitest_1.vi.fn(() => mockActiveSpan),
79
+ getRootSpan: vitest_1.vi.fn(() => mockRootSpan),
80
+ getCurrentScope: vitest_1.vi.fn(() => ({
81
+ getSession: () => mockSentrySession,
82
+ })),
83
+ captureSession: vitest_1.vi.fn(),
84
+ flush: vitest_1.vi.fn(() => Promise.resolve(true)),
85
+ setTag: vitest_1.vi.fn(),
86
+ captureException: vitest_1.vi.fn(() => 'id'),
87
+ };
88
+ });
67
89
  function mockUserResponse(fn, response) {
68
90
  fn.mockReturnValueOnce(response);
69
91
  }
@@ -255,30 +277,10 @@ function mockUserResponse(fn, response) {
255
277
  });
256
278
  });
257
279
  (0, vitest_1.describe)('abort', () => {
258
- const sentryTxn = {
259
- setStatus: vitest_1.vi.fn(),
260
- finish: vitest_1.vi.fn(),
261
- };
262
- let sentrySession = {
263
- status: 999,
264
- };
265
280
  (0, vitest_1.beforeEach)(() => {
266
281
  vitest_1.vi.clearAllMocks();
267
- sentrySession = {
268
- status: 999,
269
- };
270
- });
271
- vitest_1.vi.spyOn(Sentry, 'getCurrentHub').mockReturnValue({
272
- getScope: () => ({
273
- // @ts-expect-error - don't care about the rest of the required props value
274
- getTransaction: () => sentryTxn,
275
- // @ts-expect-error - don't care about the rest of the required props value
276
- getSession: () => sentrySession,
277
- }),
278
- captureSession: vitest_1.vi.fn(),
282
+ mockSentrySession = { status: 999 };
279
283
  });
280
- const flushSpy = vitest_1.vi.fn(() => Promise.resolve(true));
281
- vitest_1.vi.spyOn(Sentry, 'flush').mockImplementation(flushSpy);
282
284
  (0, vitest_1.it)('ends the process with an error exit code by default', async () => {
283
285
  // @ts-expect-error - vitest doesn't like the empty function
284
286
  // eslint-disable-next-line @typescript-eslint/no-empty-function
@@ -287,10 +289,13 @@ function mockUserResponse(fn, response) {
287
289
  (0, vitest_1.expect)(exitSpy).toHaveBeenCalledWith(1);
288
290
  (0, vitest_1.expect)(clackMock.outro).toHaveBeenCalledTimes(1);
289
291
  (0, vitest_1.expect)(clackMock.outro).toHaveBeenCalledWith('Wizard setup cancelled.');
290
- (0, vitest_1.expect)(sentryTxn.setStatus).toHaveBeenLastCalledWith('aborted');
291
- (0, vitest_1.expect)(sentryTxn.finish).toHaveBeenCalledTimes(1);
292
- (0, vitest_1.expect)(sentrySession.status).toBe('crashed');
293
- (0, vitest_1.expect)(flushSpy).toHaveBeenLastCalledWith(3000);
292
+ (0, vitest_1.expect)(mockRootSpan.setStatus).toHaveBeenLastCalledWith({
293
+ code: 2,
294
+ message: 'aborted',
295
+ });
296
+ (0, vitest_1.expect)(mockRootSpan.end).toHaveBeenCalledTimes(1);
297
+ (0, vitest_1.expect)(mockSentrySession.status).toBe('crashed');
298
+ (0, vitest_1.expect)(Sentry.flush).toHaveBeenLastCalledWith(3000);
294
299
  });
295
300
  (0, vitest_1.it)('ends the process with a custom exit code and message if provided', async () => {
296
301
  // @ts-expect-error - vitest doesn't like the empty function
@@ -300,10 +305,13 @@ function mockUserResponse(fn, response) {
300
305
  (0, vitest_1.expect)(exitSpy).toHaveBeenCalledWith(0);
301
306
  (0, vitest_1.expect)(clackMock.outro).toHaveBeenCalledTimes(1);
302
307
  (0, vitest_1.expect)(clackMock.outro).toHaveBeenCalledWith('Bye');
303
- (0, vitest_1.expect)(sentryTxn.setStatus).toHaveBeenLastCalledWith('cancelled');
304
- (0, vitest_1.expect)(sentryTxn.finish).toHaveBeenCalledTimes(1);
305
- (0, vitest_1.expect)(sentrySession.status).toBe('abnormal');
306
- (0, vitest_1.expect)(flushSpy).toHaveBeenLastCalledWith(3000);
308
+ (0, vitest_1.expect)(mockRootSpan.setStatus).toHaveBeenLastCalledWith({
309
+ code: 1,
310
+ message: 'cancelled',
311
+ });
312
+ (0, vitest_1.expect)(mockRootSpan.end).toHaveBeenCalledTimes(1);
313
+ (0, vitest_1.expect)(mockSentrySession.status).toBe('abnormal');
314
+ (0, vitest_1.expect)(Sentry.flush).toHaveBeenLastCalledWith(3000);
307
315
  });
308
316
  });
309
317
  (0, vitest_1.describe)('getPackageManager', () => {
@@ -1 +1 @@
1
- {"version":3,"file":"index.test.js","sourceRoot":"","sources":["../../../../test/utils/clack/index.test.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n abort,\n askForToolConfigPath,\n askForWizardLogin,\n createNewConfigFile,\n getPackageManager,\n installPackage,\n} from '../../../src/utils/clack/';\n\nimport * as fs from 'node:fs';\nimport * as ChildProcess from 'node:child_process';\nimport type { PackageManager } from '../../../src/utils/package-manager';\nimport * as PackageManagerUtils from '../../../src/utils/package-manager';\n\nimport {\n NPM,\n PNPM,\n YARN_V1,\n YARN_V2,\n} from '../../../src/utils/package-manager';\n\nimport axios from 'axios';\n\n// @ts-expect-error - clack is ESM and TS complains about that. It works though\nimport * as clack from '@clack/prompts';\n\nimport * as Sentry from '@sentry/node';\n\nimport {\n vi,\n it,\n describe,\n expect,\n beforeEach,\n Mocked,\n Mock,\n afterEach,\n} from 'vitest';\n\nvi.mock('node:child_process', async () => ({\n __esModule: true,\n ...(await vi.importActual<typeof ChildProcess>('node:child_process')),\n}));\n\nvi.mock('@clack/prompts', () => ({\n log: {\n info: vi.fn(),\n success: vi.fn(),\n warn: vi.fn(),\n error: vi.fn(),\n },\n outro: vi.fn(),\n text: vi.fn(),\n confirm: vi.fn(),\n cancel: vi.fn(),\n // passthrough for abortIfCancelled\n isCancel: vi.fn().mockReturnValue(false),\n spinner: vi\n .fn()\n .mockImplementation(() => ({ start: vi.fn(), stop: vi.fn() })),\n select: vi.fn(),\n}));\nconst clackMock = clack as Mocked<typeof clack>;\n\nvi.mock('axios');\nconst mockedAxios = axios as Mocked<typeof axios>;\n\nvi.mock('opn', () => ({\n default: vi.fn(() => Promise.resolve({ on: vi.fn() })),\n}));\n\nfunction mockUserResponse(fn: Mock, response: unknown) {\n fn.mockReturnValueOnce(response);\n}\n\ndescribe('askForToolConfigPath', () => {\n afterEach(() => {\n vi.clearAllMocks();\n });\n\n it('returns undefined if users have no config file', async () => {\n mockUserResponse(clack.confirm as Mock, false);\n\n const result = await askForToolConfigPath('Webpack', 'webpack.config.js');\n\n expect(clack.confirm).toHaveBeenCalledWith(\n expect.objectContaining({\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n message: expect.stringContaining('have a Webpack config file'),\n }),\n );\n\n expect(result).toBeUndefined();\n });\n\n it('returns the path if users have a config file and the entered path is valid', async () => {\n mockUserResponse(clack.confirm as Mock, true);\n mockUserResponse(clack.text as Mock, 'my.webpack.config.js');\n\n const result = await askForToolConfigPath('Webpack', 'webpack.config.js');\n\n expect(clack.confirm).toHaveBeenCalledWith(\n expect.objectContaining({\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n message: expect.stringContaining('have a Webpack config file'),\n }),\n );\n\n expect(clack.text).toHaveBeenCalledWith(\n expect.objectContaining({\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n message: expect.stringContaining(\n 'enter the path to your Webpack config file',\n ),\n }),\n );\n\n expect(result).toBe('my.webpack.config.js');\n });\n});\n\ndescribe('createNewConfigFile', () => {\n afterEach(() => {\n vi.clearAllMocks();\n });\n\n it('writes the file to disk and returns true if the file was created successfully', async () => {\n const writeFileSpy = vi\n .spyOn(fs.promises, 'writeFile')\n .mockImplementation(vi.fn());\n\n const filename = '/webpack.config.js';\n const code = 'module.exports = {/*config...*/}';\n\n const result = await createNewConfigFile(filename, code);\n\n expect(result).toBe(true);\n expect(writeFileSpy).toHaveBeenCalledWith(filename, code);\n });\n\n it('logs more information if provided as an argument', async () => {\n vi.spyOn(fs.promises, 'writeFile').mockImplementation(vi.fn());\n\n const filename = '/webpack.config.js';\n const code = 'module.exports = {/*config...*/}';\n const moreInfo = 'More information...';\n\n await createNewConfigFile(filename, code, moreInfo);\n\n expect(clack.log.info).toHaveBeenCalledTimes(1);\n expect(clack.log.info).toHaveBeenCalledWith(\n expect.stringContaining(moreInfo),\n );\n });\n\n it('returns false and logs a warning if the file could not be created', async () => {\n const writeFileSpy = vi\n .spyOn(fs.promises, 'writeFile')\n .mockImplementation(() => Promise.reject(new Error('Could not write')));\n\n const filename = '/webpack.config.js';\n const code = 'module.exports = {/*config...*/}';\n\n const result = await createNewConfigFile(filename, code);\n\n expect(result).toBe(false);\n expect(writeFileSpy).toHaveBeenCalledWith(filename, code);\n expect(clack.log.warn).toHaveBeenCalledTimes(1);\n });\n\n it('returns false if the passed path is not absolute', async () => {\n const result = await createNewConfigFile(\n './relative/webpack.config.js',\n '',\n );\n\n expect(result).toBe(false);\n });\n});\n\ndescribe('installPackage', () => {\n afterEach(() => {\n vi.clearAllMocks();\n });\n\n const spawnSpy = vi.spyOn(ChildProcess, 'spawn').mockImplementation(() => ({\n // @ts-expect-error - not passing the full object but directly resolving\n // to simulate a successful install\n on: vi.fn((evt: 'close', cb: (args) => void) => {\n if (evt === 'close') {\n cb(0);\n }\n }),\n // @ts-expect-error - this is fine\n stderr: { on: vi.fn() },\n }));\n\n it('force-installs a package if the forceInstall flag is set', async () => {\n const packageManagerMock: PackageManager = {\n name: 'npm',\n label: 'NPM',\n installCommand: 'install',\n buildCommand: 'npm run build',\n runScriptCommand: 'npm run',\n flags: '',\n forceInstallFlag: '--force',\n detect: vi.fn(),\n addOverride: vi.fn(),\n };\n\n await installPackage({\n alreadyInstalled: false,\n packageName: '@some/package',\n packageNameDisplayLabel: '@some/package',\n forceInstall: true,\n askBeforeUpdating: false,\n packageManager: packageManagerMock,\n });\n\n expect(spawnSpy).toHaveBeenCalledWith(\n 'npm',\n ['install', '@some/package', '--force'],\n { shell: true, stdio: ['pipe', 'ignore', 'pipe'] },\n );\n });\n\n it.each([false, undefined])(\n \"doesn't force-install a package if the forceInstall flag is %s\",\n async (flag) => {\n const packageManagerMock: PackageManager = {\n name: 'npm',\n label: 'NPM',\n installCommand: 'install',\n buildCommand: 'npm run build',\n runScriptCommand: 'npm run',\n flags: '',\n forceInstallFlag: '--force',\n detect: vi.fn(),\n addOverride: vi.fn(),\n };\n\n await installPackage({\n alreadyInstalled: false,\n packageName: '@sentry/sveltekit',\n packageNameDisplayLabel: '@sentry/sveltekit',\n forceInstall: flag,\n askBeforeUpdating: false,\n packageManager: packageManagerMock,\n });\n\n expect(spawnSpy).toHaveBeenCalledWith(\n 'npm',\n ['install', '@sentry/sveltekit'],\n { shell: true, stdio: ['pipe', 'ignore', 'pipe'] },\n );\n },\n );\n\n it('adds install flags if defined', async () => {\n const packageManagerMock: PackageManager = {\n name: 'npm',\n label: 'NPM',\n installCommand: 'install',\n buildCommand: 'npm run build',\n runScriptCommand: 'npm run',\n flags: '--ignore-workspace-root-check',\n forceInstallFlag: '--force',\n detect: vi.fn(),\n addOverride: vi.fn(),\n };\n\n await installPackage({\n alreadyInstalled: false,\n packageName: '@some/package',\n packageNameDisplayLabel: '@some/package',\n forceInstall: true,\n askBeforeUpdating: false,\n packageManager: packageManagerMock,\n });\n\n expect(spawnSpy).toHaveBeenCalledWith(\n 'npm',\n\n ['install', '@some/package', '--ignore-workspace-root-check', '--force'],\n { shell: true, stdio: ['pipe', 'ignore', 'pipe'] },\n );\n });\n});\n\ndescribe('askForWizardLogin', () => {\n beforeEach(() => {\n vi.clearAllMocks();\n mockedAxios.get.mockClear();\n clackMock.confirm.mockClear();\n clackMock.confirm.mockReset();\n mockUserResponse(clack.confirm as Mock, undefined);\n });\n\n it('asks if a user already has a Sentry account by default', async () => {\n mockUserResponse(clack.confirm as Mock, Promise.resolve(true));\n\n // Provide the data object to be returned\n mockedAxios.get.mockResolvedValue({\n data: {\n hash: 'mockedHash',\n },\n });\n\n await askForWizardLogin({ url: 'https://santry.io/' });\n\n expect(clack.confirm).toHaveBeenCalledWith(\n expect.objectContaining({\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n message: expect.stringContaining('already have a Sentry account'),\n }),\n );\n });\n\n it('skips asking for if a user already has a Sentry account if org and project are pre-selected', async () => {\n mockUserResponse(clackMock.confirm as Mock, Promise.resolve(true));\n\n // Provide the data object to be returned\n mockedAxios.get.mockResolvedValue({\n data: {\n hash: 'mockedHash',\n },\n });\n\n await askForWizardLogin({\n url: 'https://santry.io/',\n orgSlug: 'my-org',\n projectSlug: 'my-project',\n });\n\n expect(clack.confirm).not.toHaveBeenCalled();\n });\n});\n\ndescribe('abort', () => {\n const sentryTxn = {\n setStatus: vi.fn(),\n finish: vi.fn(),\n };\n\n let sentrySession = {\n status: 999,\n };\n\n beforeEach(() => {\n vi.clearAllMocks();\n sentrySession = {\n status: 999,\n };\n });\n\n vi.spyOn(Sentry, 'getCurrentHub').mockReturnValue({\n getScope: () => ({\n // @ts-expect-error - don't care about the rest of the required props value\n getTransaction: () => sentryTxn,\n // @ts-expect-error - don't care about the rest of the required props value\n getSession: () => sentrySession,\n }),\n captureSession: vi.fn(),\n });\n\n const flushSpy = vi.fn(() => Promise.resolve(true));\n vi.spyOn(Sentry, 'flush').mockImplementation(flushSpy);\n\n it('ends the process with an error exit code by default', async () => {\n // @ts-expect-error - vitest doesn't like the empty function\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n const exitSpy = vi.spyOn(process, 'exit').mockImplementation(() => {});\n\n await abort();\n\n expect(exitSpy).toHaveBeenCalledWith(1);\n\n expect(clackMock.outro).toHaveBeenCalledTimes(1);\n expect(clackMock.outro).toHaveBeenCalledWith('Wizard setup cancelled.');\n\n expect(sentryTxn.setStatus).toHaveBeenLastCalledWith('aborted');\n expect(sentryTxn.finish).toHaveBeenCalledTimes(1);\n expect(sentrySession.status).toBe('crashed');\n expect(flushSpy).toHaveBeenLastCalledWith(3000);\n });\n\n it('ends the process with a custom exit code and message if provided', async () => {\n // @ts-expect-error - vitest doesn't like the empty function\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n const exitSpy = vi.spyOn(process, 'exit').mockImplementation(() => {});\n\n await abort('Bye', 0);\n\n expect(exitSpy).toHaveBeenCalledWith(0);\n\n expect(clackMock.outro).toHaveBeenCalledTimes(1);\n expect(clackMock.outro).toHaveBeenCalledWith('Bye');\n\n expect(sentryTxn.setStatus).toHaveBeenLastCalledWith('cancelled');\n expect(sentryTxn.finish).toHaveBeenCalledTimes(1);\n expect(sentrySession.status).toBe('abnormal');\n expect(flushSpy).toHaveBeenLastCalledWith(3000);\n });\n});\n\ndescribe('getPackageManager', () => {\n afterEach(() => {\n vi.clearAllMocks();\n // @ts-expect-error - this variable is set by the wizard\n delete global.__sentry_wizard_cached_package_manager;\n });\n\n it('returns the auto-detected package manager', async () => {\n const detectPacManSpy = vi\n .spyOn(PackageManagerUtils, '_detectPackageManger')\n .mockReturnValueOnce(YARN_V1);\n\n const packageManager = await getPackageManager();\n\n expect(detectPacManSpy).toHaveBeenCalledTimes(1);\n\n expect(packageManager).toBe(YARN_V1);\n });\n\n it('caches the auto-detected package manager', async () => {\n const detectPacManSpy = vi\n .spyOn(PackageManagerUtils, '_detectPackageManger')\n .mockReturnValueOnce(YARN_V1);\n\n const packageManager1 = await getPackageManager();\n const packageManager2 = await getPackageManager();\n\n expect(detectPacManSpy).toHaveBeenCalledTimes(1);\n\n expect(packageManager1).toBe(YARN_V1);\n expect(packageManager2).toBe(YARN_V1);\n });\n\n describe('when auto detection fails', () => {\n it('returns a fallback package manager if fallback is specified', async () => {\n const detectPacManSpy = vi\n .spyOn(PackageManagerUtils, '_detectPackageManger')\n .mockReturnValueOnce(null);\n\n const packageManager = await getPackageManager(YARN_V2);\n\n expect(detectPacManSpy).toHaveBeenCalledTimes(1);\n\n expect(packageManager).toBe(YARN_V2);\n });\n\n it(\"doesn't cache the fallback package manager\", async () => {\n const detectPacManSpy = vi\n .spyOn(PackageManagerUtils, '_detectPackageManger')\n .mockReturnValue(null);\n\n const packageManager1 = await getPackageManager(YARN_V2);\n const packageManager2 = await getPackageManager(NPM);\n\n expect(detectPacManSpy).toHaveBeenCalledTimes(2);\n\n expect(packageManager1).toBe(YARN_V2);\n expect(packageManager2).toBe(NPM);\n });\n\n it('returns the user-selected package manager if no fallback is provided', async () => {\n const detectPacManSpy = vi\n .spyOn(PackageManagerUtils, '_detectPackageManger')\n .mockReturnValueOnce(null);\n\n clackMock.select.mockReturnValueOnce(Promise.resolve(PNPM));\n\n const packageManager = await getPackageManager();\n\n expect(detectPacManSpy).toHaveBeenCalledTimes(1);\n expect(packageManager).toBe(PNPM);\n });\n\n it('caches the user-selected package manager', async () => {\n const detectPacManSpy = vi\n .spyOn(PackageManagerUtils, '_detectPackageManger')\n .mockReturnValueOnce(null);\n\n clackMock.select.mockReturnValueOnce(Promise.resolve(PNPM));\n\n const packageManager1 = await getPackageManager();\n const packageManager2 = await getPackageManager();\n\n expect(detectPacManSpy).toHaveBeenCalledTimes(1);\n expect(clackMock.select).toHaveBeenCalledTimes(1);\n\n expect(packageManager1).toBe(PNPM);\n expect(packageManager2).toBe(PNPM);\n });\n });\n});\n"]}
1
+ {"version":3,"file":"index.test.js","sourceRoot":"","sources":["../../../../test/utils/clack/index.test.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n abort,\n askForToolConfigPath,\n askForWizardLogin,\n createNewConfigFile,\n getPackageManager,\n installPackage,\n} from '../../../src/utils/clack/';\n\nimport * as fs from 'node:fs';\nimport * as ChildProcess from 'node:child_process';\nimport type { PackageManager } from '../../../src/utils/package-manager';\nimport * as PackageManagerUtils from '../../../src/utils/package-manager';\n\nimport {\n NPM,\n PNPM,\n YARN_V1,\n YARN_V2,\n} from '../../../src/utils/package-manager';\n\nimport axios from 'axios';\n\n// @ts-expect-error - clack is ESM and TS complains about that. It works though\nimport * as clack from '@clack/prompts';\n\nimport * as Sentry from '@sentry/node';\n\nimport {\n vi,\n it,\n describe,\n expect,\n beforeEach,\n Mocked,\n Mock,\n afterEach,\n} from 'vitest';\n\nvi.mock('node:child_process', async () => ({\n __esModule: true,\n ...(await vi.importActual<typeof ChildProcess>('node:child_process')),\n}));\n\nvi.mock('@clack/prompts', () => ({\n log: {\n info: vi.fn(),\n success: vi.fn(),\n warn: vi.fn(),\n error: vi.fn(),\n },\n outro: vi.fn(),\n text: vi.fn(),\n confirm: vi.fn(),\n cancel: vi.fn(),\n // passthrough for abortIfCancelled\n isCancel: vi.fn().mockReturnValue(false),\n spinner: vi\n .fn()\n .mockImplementation(() => ({ start: vi.fn(), stop: vi.fn() })),\n select: vi.fn(),\n}));\nconst clackMock = clack as Mocked<typeof clack>;\n\nvi.mock('axios');\nconst mockedAxios = axios as Mocked<typeof axios>;\n\nvi.mock('opn', () => ({\n default: vi.fn(() => Promise.resolve({ on: vi.fn() })),\n}));\n\n// Sentry mock functions defined at module level for the abort tests\nconst mockRootSpan = {\n setStatus: vi.fn(),\n end: vi.fn(),\n};\nconst mockActiveSpan = {};\nlet mockSentrySession = { status: 999 as number | string };\n\nvi.mock('@sentry/node', async () => {\n const actual = await vi.importActual<typeof import('@sentry/node')>(\n '@sentry/node',\n );\n return {\n ...actual,\n getActiveSpan: vi.fn(() => mockActiveSpan),\n getRootSpan: vi.fn(() => mockRootSpan),\n getCurrentScope: vi.fn(() => ({\n getSession: () => mockSentrySession,\n })),\n captureSession: vi.fn(),\n flush: vi.fn(() => Promise.resolve(true)),\n setTag: vi.fn(),\n captureException: vi.fn(() => 'id'),\n };\n});\n\nfunction mockUserResponse(fn: Mock, response: unknown) {\n fn.mockReturnValueOnce(response);\n}\n\ndescribe('askForToolConfigPath', () => {\n afterEach(() => {\n vi.clearAllMocks();\n });\n\n it('returns undefined if users have no config file', async () => {\n mockUserResponse(clack.confirm as Mock, false);\n\n const result = await askForToolConfigPath('Webpack', 'webpack.config.js');\n\n expect(clack.confirm).toHaveBeenCalledWith(\n expect.objectContaining({\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n message: expect.stringContaining('have a Webpack config file'),\n }),\n );\n\n expect(result).toBeUndefined();\n });\n\n it('returns the path if users have a config file and the entered path is valid', async () => {\n mockUserResponse(clack.confirm as Mock, true);\n mockUserResponse(clack.text as Mock, 'my.webpack.config.js');\n\n const result = await askForToolConfigPath('Webpack', 'webpack.config.js');\n\n expect(clack.confirm).toHaveBeenCalledWith(\n expect.objectContaining({\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n message: expect.stringContaining('have a Webpack config file'),\n }),\n );\n\n expect(clack.text).toHaveBeenCalledWith(\n expect.objectContaining({\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n message: expect.stringContaining(\n 'enter the path to your Webpack config file',\n ),\n }),\n );\n\n expect(result).toBe('my.webpack.config.js');\n });\n});\n\ndescribe('createNewConfigFile', () => {\n afterEach(() => {\n vi.clearAllMocks();\n });\n\n it('writes the file to disk and returns true if the file was created successfully', async () => {\n const writeFileSpy = vi\n .spyOn(fs.promises, 'writeFile')\n .mockImplementation(vi.fn());\n\n const filename = '/webpack.config.js';\n const code = 'module.exports = {/*config...*/}';\n\n const result = await createNewConfigFile(filename, code);\n\n expect(result).toBe(true);\n expect(writeFileSpy).toHaveBeenCalledWith(filename, code);\n });\n\n it('logs more information if provided as an argument', async () => {\n vi.spyOn(fs.promises, 'writeFile').mockImplementation(vi.fn());\n\n const filename = '/webpack.config.js';\n const code = 'module.exports = {/*config...*/}';\n const moreInfo = 'More information...';\n\n await createNewConfigFile(filename, code, moreInfo);\n\n expect(clack.log.info).toHaveBeenCalledTimes(1);\n expect(clack.log.info).toHaveBeenCalledWith(\n expect.stringContaining(moreInfo),\n );\n });\n\n it('returns false and logs a warning if the file could not be created', async () => {\n const writeFileSpy = vi\n .spyOn(fs.promises, 'writeFile')\n .mockImplementation(() => Promise.reject(new Error('Could not write')));\n\n const filename = '/webpack.config.js';\n const code = 'module.exports = {/*config...*/}';\n\n const result = await createNewConfigFile(filename, code);\n\n expect(result).toBe(false);\n expect(writeFileSpy).toHaveBeenCalledWith(filename, code);\n expect(clack.log.warn).toHaveBeenCalledTimes(1);\n });\n\n it('returns false if the passed path is not absolute', async () => {\n const result = await createNewConfigFile(\n './relative/webpack.config.js',\n '',\n );\n\n expect(result).toBe(false);\n });\n});\n\ndescribe('installPackage', () => {\n afterEach(() => {\n vi.clearAllMocks();\n });\n\n const spawnSpy = vi.spyOn(ChildProcess, 'spawn').mockImplementation(() => ({\n // @ts-expect-error - not passing the full object but directly resolving\n // to simulate a successful install\n on: vi.fn((evt: 'close', cb: (args) => void) => {\n if (evt === 'close') {\n cb(0);\n }\n }),\n // @ts-expect-error - this is fine\n stderr: { on: vi.fn() },\n }));\n\n it('force-installs a package if the forceInstall flag is set', async () => {\n const packageManagerMock: PackageManager = {\n name: 'npm',\n label: 'NPM',\n installCommand: 'install',\n buildCommand: 'npm run build',\n runScriptCommand: 'npm run',\n flags: '',\n forceInstallFlag: '--force',\n detect: vi.fn(),\n addOverride: vi.fn(),\n };\n\n await installPackage({\n alreadyInstalled: false,\n packageName: '@some/package',\n packageNameDisplayLabel: '@some/package',\n forceInstall: true,\n askBeforeUpdating: false,\n packageManager: packageManagerMock,\n });\n\n expect(spawnSpy).toHaveBeenCalledWith(\n 'npm',\n ['install', '@some/package', '--force'],\n { shell: true, stdio: ['pipe', 'ignore', 'pipe'] },\n );\n });\n\n it.each([false, undefined])(\n \"doesn't force-install a package if the forceInstall flag is %s\",\n async (flag) => {\n const packageManagerMock: PackageManager = {\n name: 'npm',\n label: 'NPM',\n installCommand: 'install',\n buildCommand: 'npm run build',\n runScriptCommand: 'npm run',\n flags: '',\n forceInstallFlag: '--force',\n detect: vi.fn(),\n addOverride: vi.fn(),\n };\n\n await installPackage({\n alreadyInstalled: false,\n packageName: '@sentry/sveltekit',\n packageNameDisplayLabel: '@sentry/sveltekit',\n forceInstall: flag,\n askBeforeUpdating: false,\n packageManager: packageManagerMock,\n });\n\n expect(spawnSpy).toHaveBeenCalledWith(\n 'npm',\n ['install', '@sentry/sveltekit'],\n { shell: true, stdio: ['pipe', 'ignore', 'pipe'] },\n );\n },\n );\n\n it('adds install flags if defined', async () => {\n const packageManagerMock: PackageManager = {\n name: 'npm',\n label: 'NPM',\n installCommand: 'install',\n buildCommand: 'npm run build',\n runScriptCommand: 'npm run',\n flags: '--ignore-workspace-root-check',\n forceInstallFlag: '--force',\n detect: vi.fn(),\n addOverride: vi.fn(),\n };\n\n await installPackage({\n alreadyInstalled: false,\n packageName: '@some/package',\n packageNameDisplayLabel: '@some/package',\n forceInstall: true,\n askBeforeUpdating: false,\n packageManager: packageManagerMock,\n });\n\n expect(spawnSpy).toHaveBeenCalledWith(\n 'npm',\n\n ['install', '@some/package', '--ignore-workspace-root-check', '--force'],\n { shell: true, stdio: ['pipe', 'ignore', 'pipe'] },\n );\n });\n});\n\ndescribe('askForWizardLogin', () => {\n beforeEach(() => {\n vi.clearAllMocks();\n mockedAxios.get.mockClear();\n clackMock.confirm.mockClear();\n clackMock.confirm.mockReset();\n mockUserResponse(clack.confirm as Mock, undefined);\n });\n\n it('asks if a user already has a Sentry account by default', async () => {\n mockUserResponse(clack.confirm as Mock, Promise.resolve(true));\n\n // Provide the data object to be returned\n mockedAxios.get.mockResolvedValue({\n data: {\n hash: 'mockedHash',\n },\n });\n\n await askForWizardLogin({ url: 'https://santry.io/' });\n\n expect(clack.confirm).toHaveBeenCalledWith(\n expect.objectContaining({\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n message: expect.stringContaining('already have a Sentry account'),\n }),\n );\n });\n\n it('skips asking for if a user already has a Sentry account if org and project are pre-selected', async () => {\n mockUserResponse(clackMock.confirm as Mock, Promise.resolve(true));\n\n // Provide the data object to be returned\n mockedAxios.get.mockResolvedValue({\n data: {\n hash: 'mockedHash',\n },\n });\n\n await askForWizardLogin({\n url: 'https://santry.io/',\n orgSlug: 'my-org',\n projectSlug: 'my-project',\n });\n\n expect(clack.confirm).not.toHaveBeenCalled();\n });\n});\n\ndescribe('abort', () => {\n beforeEach(() => {\n vi.clearAllMocks();\n mockSentrySession = { status: 999 };\n });\n\n it('ends the process with an error exit code by default', async () => {\n // @ts-expect-error - vitest doesn't like the empty function\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n const exitSpy = vi.spyOn(process, 'exit').mockImplementation(() => {});\n\n await abort();\n\n expect(exitSpy).toHaveBeenCalledWith(1);\n\n expect(clackMock.outro).toHaveBeenCalledTimes(1);\n expect(clackMock.outro).toHaveBeenCalledWith('Wizard setup cancelled.');\n\n expect(mockRootSpan.setStatus).toHaveBeenLastCalledWith({\n code: 2,\n message: 'aborted',\n });\n expect(mockRootSpan.end).toHaveBeenCalledTimes(1);\n expect(mockSentrySession.status).toBe('crashed');\n expect(Sentry.flush).toHaveBeenLastCalledWith(3000);\n });\n\n it('ends the process with a custom exit code and message if provided', async () => {\n // @ts-expect-error - vitest doesn't like the empty function\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n const exitSpy = vi.spyOn(process, 'exit').mockImplementation(() => {});\n\n await abort('Bye', 0);\n\n expect(exitSpy).toHaveBeenCalledWith(0);\n\n expect(clackMock.outro).toHaveBeenCalledTimes(1);\n expect(clackMock.outro).toHaveBeenCalledWith('Bye');\n\n expect(mockRootSpan.setStatus).toHaveBeenLastCalledWith({\n code: 1,\n message: 'cancelled',\n });\n expect(mockRootSpan.end).toHaveBeenCalledTimes(1);\n expect(mockSentrySession.status).toBe('abnormal');\n expect(Sentry.flush).toHaveBeenLastCalledWith(3000);\n });\n});\n\ndescribe('getPackageManager', () => {\n afterEach(() => {\n vi.clearAllMocks();\n // @ts-expect-error - this variable is set by the wizard\n delete global.__sentry_wizard_cached_package_manager;\n });\n\n it('returns the auto-detected package manager', async () => {\n const detectPacManSpy = vi\n .spyOn(PackageManagerUtils, '_detectPackageManger')\n .mockReturnValueOnce(YARN_V1);\n\n const packageManager = await getPackageManager();\n\n expect(detectPacManSpy).toHaveBeenCalledTimes(1);\n\n expect(packageManager).toBe(YARN_V1);\n });\n\n it('caches the auto-detected package manager', async () => {\n const detectPacManSpy = vi\n .spyOn(PackageManagerUtils, '_detectPackageManger')\n .mockReturnValueOnce(YARN_V1);\n\n const packageManager1 = await getPackageManager();\n const packageManager2 = await getPackageManager();\n\n expect(detectPacManSpy).toHaveBeenCalledTimes(1);\n\n expect(packageManager1).toBe(YARN_V1);\n expect(packageManager2).toBe(YARN_V1);\n });\n\n describe('when auto detection fails', () => {\n it('returns a fallback package manager if fallback is specified', async () => {\n const detectPacManSpy = vi\n .spyOn(PackageManagerUtils, '_detectPackageManger')\n .mockReturnValueOnce(null);\n\n const packageManager = await getPackageManager(YARN_V2);\n\n expect(detectPacManSpy).toHaveBeenCalledTimes(1);\n\n expect(packageManager).toBe(YARN_V2);\n });\n\n it(\"doesn't cache the fallback package manager\", async () => {\n const detectPacManSpy = vi\n .spyOn(PackageManagerUtils, '_detectPackageManger')\n .mockReturnValue(null);\n\n const packageManager1 = await getPackageManager(YARN_V2);\n const packageManager2 = await getPackageManager(NPM);\n\n expect(detectPacManSpy).toHaveBeenCalledTimes(2);\n\n expect(packageManager1).toBe(YARN_V2);\n expect(packageManager2).toBe(NPM);\n });\n\n it('returns the user-selected package manager if no fallback is provided', async () => {\n const detectPacManSpy = vi\n .spyOn(PackageManagerUtils, '_detectPackageManger')\n .mockReturnValueOnce(null);\n\n clackMock.select.mockReturnValueOnce(Promise.resolve(PNPM));\n\n const packageManager = await getPackageManager();\n\n expect(detectPacManSpy).toHaveBeenCalledTimes(1);\n expect(packageManager).toBe(PNPM);\n });\n\n it('caches the user-selected package manager', async () => {\n const detectPacManSpy = vi\n .spyOn(PackageManagerUtils, '_detectPackageManger')\n .mockReturnValueOnce(null);\n\n clackMock.select.mockReturnValueOnce(Promise.resolve(PNPM));\n\n const packageManager1 = await getPackageManager();\n const packageManager2 = await getPackageManager();\n\n expect(detectPacManSpy).toHaveBeenCalledTimes(1);\n expect(clackMock.select).toHaveBeenCalledTimes(1);\n\n expect(packageManager1).toBe(PNPM);\n expect(packageManager2).toBe(PNPM);\n });\n });\n});\n"]}
@@ -37,6 +37,7 @@ vitest_1.vi.mock('../../../src/utils/clack', () => ({
37
37
  vitest_1.vi.mock('@clack/prompts', () => ({
38
38
  confirm: vitest_1.vi.fn(),
39
39
  select: vitest_1.vi.fn(),
40
+ multiselect: vitest_1.vi.fn(),
40
41
  isCancel: vitest_1.vi.fn(() => false),
41
42
  cancel: vitest_1.vi.fn(),
42
43
  log: {
@@ -77,9 +78,8 @@ vitest_1.vi.mock('node:child_process');
77
78
  });
78
79
  (0, vitest_1.it)('should configure for Cursor when selected', async () => {
79
80
  const { clack, clackUtils } = await getMocks();
80
- vitest_1.vi.mocked(clack.select)
81
- .mockResolvedValueOnce('yes')
82
- .mockResolvedValueOnce('cursor');
81
+ vitest_1.vi.mocked(clack.select).mockResolvedValueOnce('yes');
82
+ vitest_1.vi.mocked(clack.multiselect).mockResolvedValueOnce(['cursor']);
83
83
  vitest_1.vi.mocked(clackUtils.abortIfCancelled).mockImplementation((value) => Promise.resolve(value));
84
84
  const mockReadFile = vitest_1.vi
85
85
  .fn()
@@ -90,9 +90,8 @@ vitest_1.vi.mock('node:child_process');
90
90
  vitest_1.vi.spyOn(fs.promises, 'writeFile').mockImplementation(mockWriteFile);
91
91
  vitest_1.vi.spyOn(fs, 'mkdirSync').mockImplementation(mockMkdirSync);
92
92
  await (0, mcp_config_1.offerProjectScopedMcpConfig)();
93
- (0, vitest_1.expect)(clack.select).toHaveBeenCalledTimes(2);
94
- (0, vitest_1.expect)(clack.select).toHaveBeenNthCalledWith(2, vitest_1.expect.objectContaining({
95
- message: 'Which editor do you want to configure?',
93
+ (0, vitest_1.expect)(clack.multiselect).toHaveBeenCalledWith(vitest_1.expect.objectContaining({
94
+ message: 'Which editor(s) do you want to configure?',
96
95
  options: vitest_1.expect.arrayContaining([
97
96
  vitest_1.expect.objectContaining({ value: 'cursor' }),
98
97
  vitest_1.expect.objectContaining({ value: 'vscode' }),
@@ -101,14 +100,13 @@ vitest_1.vi.mock('node:child_process');
101
100
  }));
102
101
  (0, vitest_1.expect)(mockWriteFile).toHaveBeenCalledWith(vitest_1.expect.stringContaining('.cursor/mcp.json'), vitest_1.expect.stringContaining('"mcpServers"'), 'utf8');
103
102
  (0, vitest_1.expect)(clack.log.success).toHaveBeenCalledWith(vitest_1.expect.stringContaining('.cursor/mcp.json'));
104
- (0, vitest_1.expect)(clack.log.success).toHaveBeenCalledWith('Added project-scoped Sentry MCP configuration.');
103
+ (0, vitest_1.expect)(clack.log.success).toHaveBeenCalledWith('Added project-scoped Sentry MCP configuration for Cursor.');
105
104
  (0, vitest_1.expect)(clack.log.info).toHaveBeenCalledWith(vitest_1.expect.stringContaining('reload your editor'));
106
105
  });
107
106
  (0, vitest_1.it)('should configure for VS Code when selected', async () => {
108
107
  const { clack, clackUtils } = await getMocks();
109
- vitest_1.vi.mocked(clack.select)
110
- .mockResolvedValueOnce('yes')
111
- .mockResolvedValueOnce('vscode');
108
+ vitest_1.vi.mocked(clack.select).mockResolvedValueOnce('yes');
109
+ vitest_1.vi.mocked(clack.multiselect).mockResolvedValueOnce(['vscode']);
112
110
  vitest_1.vi.mocked(clackUtils.abortIfCancelled).mockImplementation((value) => Promise.resolve(value));
113
111
  const mockReadFile = vitest_1.vi
114
112
  .fn()
@@ -124,9 +122,8 @@ vitest_1.vi.mock('node:child_process');
124
122
  });
125
123
  (0, vitest_1.it)('should configure for Claude Code when selected', async () => {
126
124
  const { clack, clackUtils } = await getMocks();
127
- vitest_1.vi.mocked(clack.select)
128
- .mockResolvedValueOnce('yes')
129
- .mockResolvedValueOnce('claudeCode');
125
+ vitest_1.vi.mocked(clack.select).mockResolvedValueOnce('yes');
126
+ vitest_1.vi.mocked(clack.multiselect).mockResolvedValueOnce(['claudeCode']);
130
127
  vitest_1.vi.mocked(clackUtils.abortIfCancelled).mockImplementation((value) => Promise.resolve(value));
131
128
  const mockReadFile = vitest_1.vi
132
129
  .fn()
@@ -142,9 +139,8 @@ vitest_1.vi.mock('node:child_process');
142
139
  });
143
140
  (0, vitest_1.it)('should update existing Cursor config file', async () => {
144
141
  const { clack, clackUtils } = await getMocks();
145
- vitest_1.vi.mocked(clack.select)
146
- .mockResolvedValueOnce('yes')
147
- .mockResolvedValueOnce('cursor');
142
+ vitest_1.vi.mocked(clack.select).mockResolvedValueOnce('yes');
143
+ vitest_1.vi.mocked(clack.multiselect).mockResolvedValueOnce(['cursor']);
148
144
  vitest_1.vi.mocked(clackUtils.abortIfCancelled).mockImplementation((value) => Promise.resolve(value));
149
145
  const existingConfig = JSON.stringify({
150
146
  mcpServers: {
@@ -169,9 +165,8 @@ vitest_1.vi.mock('node:child_process');
169
165
  });
170
166
  (0, vitest_1.it)('should update existing VS Code config file', async () => {
171
167
  const { clack, clackUtils } = await getMocks();
172
- vitest_1.vi.mocked(clack.select)
173
- .mockResolvedValueOnce('yes')
174
- .mockResolvedValueOnce('vscode');
168
+ vitest_1.vi.mocked(clack.select).mockResolvedValueOnce('yes');
169
+ vitest_1.vi.mocked(clack.multiselect).mockResolvedValueOnce(['vscode']);
175
170
  vitest_1.vi.mocked(clackUtils.abortIfCancelled).mockImplementation((value) => Promise.resolve(value));
176
171
  const existingConfig = JSON.stringify({
177
172
  servers: {
@@ -196,9 +191,8 @@ vitest_1.vi.mock('node:child_process');
196
191
  });
197
192
  (0, vitest_1.it)('should update existing Claude Code config file', async () => {
198
193
  const { clack, clackUtils } = await getMocks();
199
- vitest_1.vi.mocked(clack.select)
200
- .mockResolvedValueOnce('yes')
201
- .mockResolvedValueOnce('claudeCode');
194
+ vitest_1.vi.mocked(clack.select).mockResolvedValueOnce('yes');
195
+ vitest_1.vi.mocked(clack.multiselect).mockResolvedValueOnce(['claudeCode']);
202
196
  vitest_1.vi.mocked(clackUtils.abortIfCancelled).mockImplementation((value) => Promise.resolve(value));
203
197
  const existingConfig = JSON.stringify({
204
198
  mcpServers: {
@@ -219,11 +213,85 @@ vitest_1.vi.mock('node:child_process');
219
213
  (0, vitest_1.expect)(writtenContent.mcpServers).toHaveProperty('Sentry');
220
214
  (0, vitest_1.expect)(clack.log.success).toHaveBeenCalledWith('Updated .mcp.json');
221
215
  });
216
+ (0, vitest_1.it)('should configure for OpenCode when selected', async () => {
217
+ const { clack, clackUtils } = await getMocks();
218
+ vitest_1.vi.mocked(clack.select).mockResolvedValueOnce('yes');
219
+ vitest_1.vi.mocked(clack.multiselect).mockResolvedValueOnce(['openCode']);
220
+ vitest_1.vi.mocked(clackUtils.abortIfCancelled).mockImplementation((value) => Promise.resolve(value));
221
+ const mockReadFile = vitest_1.vi
222
+ .fn()
223
+ .mockRejectedValue(new Error('File not found'));
224
+ const mockWriteFile = vitest_1.vi.fn().mockResolvedValue(undefined);
225
+ const mockMkdirSync = vitest_1.vi.fn();
226
+ vitest_1.vi.spyOn(fs.promises, 'readFile').mockImplementation(mockReadFile);
227
+ vitest_1.vi.spyOn(fs.promises, 'writeFile').mockImplementation(mockWriteFile);
228
+ vitest_1.vi.spyOn(fs, 'mkdirSync').mockImplementation(mockMkdirSync);
229
+ await (0, mcp_config_1.offerProjectScopedMcpConfig)();
230
+ (0, vitest_1.expect)(mockWriteFile).toHaveBeenCalledWith(vitest_1.expect.stringContaining('opencode.json'), vitest_1.expect.stringContaining('"mcp"'), 'utf8');
231
+ // Verify the written content has the correct structure for OpenCode
232
+ const writtenContent = JSON.parse(mockWriteFile.mock.calls[0][1]);
233
+ (0, vitest_1.expect)(writtenContent.$schema).toBe('https://opencode.ai/config.json');
234
+ (0, vitest_1.expect)(writtenContent.mcp).toHaveProperty('Sentry');
235
+ (0, vitest_1.expect)(writtenContent.mcp?.Sentry).toHaveProperty('type', 'remote');
236
+ (0, vitest_1.expect)(writtenContent.mcp?.Sentry).toHaveProperty('url');
237
+ (0, vitest_1.expect)(writtenContent.mcp?.Sentry?.oauth).toEqual({});
238
+ (0, vitest_1.expect)(clack.log.success).toHaveBeenCalledWith(vitest_1.expect.stringContaining('opencode.json'));
239
+ (0, vitest_1.expect)(clack.log.success).toHaveBeenCalledWith('Added project-scoped Sentry MCP configuration for OpenCode.');
240
+ (0, vitest_1.expect)(clack.log.info).toHaveBeenCalledWith(vitest_1.expect.stringContaining('restart OpenCode'));
241
+ });
242
+ (0, vitest_1.it)('should update existing OpenCode config file', async () => {
243
+ const { clack, clackUtils } = await getMocks();
244
+ vitest_1.vi.mocked(clack.select).mockResolvedValueOnce('yes');
245
+ vitest_1.vi.mocked(clack.multiselect).mockResolvedValueOnce(['openCode']);
246
+ vitest_1.vi.mocked(clackUtils.abortIfCancelled).mockImplementation((value) => Promise.resolve(value));
247
+ const existingConfig = JSON.stringify({
248
+ mcp: {
249
+ OtherServer: {
250
+ type: 'remote',
251
+ url: 'https://other.example.com',
252
+ },
253
+ },
254
+ });
255
+ const mockReadFile = vitest_1.vi.fn().mockResolvedValue(existingConfig);
256
+ const mockWriteFile = vitest_1.vi.fn().mockResolvedValue(undefined);
257
+ const mockMkdirSync = vitest_1.vi.fn();
258
+ vitest_1.vi.spyOn(fs.promises, 'readFile').mockImplementation(mockReadFile);
259
+ vitest_1.vi.spyOn(fs.promises, 'writeFile').mockImplementation(mockWriteFile);
260
+ vitest_1.vi.spyOn(fs, 'mkdirSync').mockImplementation(mockMkdirSync);
261
+ await (0, mcp_config_1.offerProjectScopedMcpConfig)();
262
+ const writtenContent = JSON.parse(mockWriteFile.mock.calls[0][1]);
263
+ (0, vitest_1.expect)(writtenContent.mcp).toHaveProperty('OtherServer');
264
+ (0, vitest_1.expect)(writtenContent.mcp).toHaveProperty('Sentry');
265
+ (0, vitest_1.expect)(writtenContent.mcp?.Sentry).toHaveProperty('type', 'remote');
266
+ (0, vitest_1.expect)(clack.log.success).toHaveBeenCalledWith('Updated opencode.json');
267
+ });
268
+ (0, vitest_1.it)('should handle file write errors gracefully for OpenCode', async () => {
269
+ const { clack, clackUtils } = await getMocks();
270
+ vitest_1.vi.mocked(clack.select).mockResolvedValueOnce('yes');
271
+ vitest_1.vi.mocked(clack.multiselect).mockResolvedValueOnce(['openCode']);
272
+ vitest_1.vi.mocked(clackUtils.abortIfCancelled).mockImplementation((value) => Promise.resolve(value));
273
+ const mockReadFile = vitest_1.vi
274
+ .fn()
275
+ .mockRejectedValue(new Error('File not found'));
276
+ const mockWriteFile = vitest_1.vi
277
+ .fn()
278
+ .mockRejectedValue(new Error('Permission denied'));
279
+ const mockMkdirSync = vitest_1.vi.fn();
280
+ vitest_1.vi.spyOn(fs.promises, 'readFile').mockImplementation(mockReadFile);
281
+ vitest_1.vi.spyOn(fs.promises, 'writeFile').mockImplementation(mockWriteFile);
282
+ vitest_1.vi.spyOn(fs, 'mkdirSync').mockImplementation(mockMkdirSync);
283
+ await (0, vitest_1.expect)((0, mcp_config_1.offerProjectScopedMcpConfig)()).resolves.toBeUndefined();
284
+ (0, vitest_1.expect)(clack.log.warn).toHaveBeenCalledWith(vitest_1.expect.stringContaining('Failed to write MCP config for openCode'));
285
+ (0, vitest_1.expect)(clackUtils.showCopyPasteInstructions).toHaveBeenCalledWith(vitest_1.expect.objectContaining({
286
+ filename: 'opencode.json',
287
+ codeSnippet: vitest_1.expect.stringContaining('"mcp"'),
288
+ hint: 'create the file if it does not exist',
289
+ }));
290
+ });
222
291
  (0, vitest_1.it)('should handle file write errors gracefully for Cursor', async () => {
223
292
  const { clack, clackUtils } = await getMocks();
224
- vitest_1.vi.mocked(clack.select)
225
- .mockResolvedValueOnce('yes')
226
- .mockResolvedValueOnce('cursor');
293
+ vitest_1.vi.mocked(clack.select).mockResolvedValueOnce('yes');
294
+ vitest_1.vi.mocked(clack.multiselect).mockResolvedValueOnce(['cursor']);
227
295
  vitest_1.vi.mocked(clackUtils.abortIfCancelled).mockImplementation((value) => Promise.resolve(value));
228
296
  const mockReadFile = vitest_1.vi
229
297
  .fn()
@@ -236,7 +304,7 @@ vitest_1.vi.mock('node:child_process');
236
304
  vitest_1.vi.spyOn(fs.promises, 'writeFile').mockImplementation(mockWriteFile);
237
305
  vitest_1.vi.spyOn(fs, 'mkdirSync').mockImplementation(mockMkdirSync);
238
306
  await (0, vitest_1.expect)((0, mcp_config_1.offerProjectScopedMcpConfig)()).resolves.toBeUndefined();
239
- (0, vitest_1.expect)(clack.log.warn).toHaveBeenCalledWith(vitest_1.expect.stringContaining('Failed to write MCP config automatically'));
307
+ (0, vitest_1.expect)(clack.log.warn).toHaveBeenCalledWith(vitest_1.expect.stringContaining('Failed to write MCP config'));
240
308
  (0, vitest_1.expect)(clackUtils.showCopyPasteInstructions).toHaveBeenCalledWith(vitest_1.expect.objectContaining({
241
309
  filename: path.join('.cursor', 'mcp.json'),
242
310
  codeSnippet: vitest_1.expect.stringContaining('mcpServers'),
@@ -245,9 +313,8 @@ vitest_1.vi.mock('node:child_process');
245
313
  });
246
314
  (0, vitest_1.it)('should handle file write errors gracefully for VS Code', async () => {
247
315
  const { clack, clackUtils } = await getMocks();
248
- vitest_1.vi.mocked(clack.select)
249
- .mockResolvedValueOnce('yes')
250
- .mockResolvedValueOnce('vscode');
316
+ vitest_1.vi.mocked(clack.select).mockResolvedValueOnce('yes');
317
+ vitest_1.vi.mocked(clack.multiselect).mockResolvedValueOnce(['vscode']);
251
318
  vitest_1.vi.mocked(clackUtils.abortIfCancelled).mockImplementation((value) => Promise.resolve(value));
252
319
  const mockReadFile = vitest_1.vi
253
320
  .fn()
@@ -268,9 +335,8 @@ vitest_1.vi.mock('node:child_process');
268
335
  });
269
336
  (0, vitest_1.it)('should handle file write errors gracefully for Claude Code', async () => {
270
337
  const { clack, clackUtils } = await getMocks();
271
- vitest_1.vi.mocked(clack.select)
272
- .mockResolvedValueOnce('yes')
273
- .mockResolvedValueOnce('claudeCode');
338
+ vitest_1.vi.mocked(clack.select).mockResolvedValueOnce('yes');
339
+ vitest_1.vi.mocked(clack.multiselect).mockResolvedValueOnce(['claudeCode']);
274
340
  vitest_1.vi.mocked(clackUtils.abortIfCancelled).mockImplementation((value) => Promise.resolve(value));
275
341
  const mockReadFile = vitest_1.vi
276
342
  .fn()
@@ -291,9 +357,8 @@ vitest_1.vi.mock('node:child_process');
291
357
  });
292
358
  (0, vitest_1.it)('should handle update errors and show copy-paste instructions', async () => {
293
359
  const { clack, clackUtils } = await getMocks();
294
- vitest_1.vi.mocked(clack.select)
295
- .mockResolvedValueOnce('yes')
296
- .mockResolvedValueOnce('cursor');
360
+ vitest_1.vi.mocked(clack.select).mockResolvedValueOnce('yes');
361
+ vitest_1.vi.mocked(clack.multiselect).mockResolvedValueOnce(['cursor']);
297
362
  vitest_1.vi.mocked(clackUtils.abortIfCancelled).mockImplementation((value) => Promise.resolve(value));
298
363
  // Mock existing file and simulate write error during update
299
364
  const existingConfig = JSON.stringify({
@@ -312,14 +377,13 @@ vitest_1.vi.mock('node:child_process');
312
377
  vitest_1.vi.spyOn(fs.promises, 'writeFile').mockImplementation(mockWriteFile);
313
378
  vitest_1.vi.spyOn(fs, 'mkdirSync').mockImplementation(mockMkdirSync);
314
379
  await (0, vitest_1.expect)((0, mcp_config_1.offerProjectScopedMcpConfig)()).resolves.toBeUndefined();
315
- (0, vitest_1.expect)(clack.log.warn).toHaveBeenCalledWith(vitest_1.expect.stringContaining('Failed to write MCP config automatically'));
380
+ (0, vitest_1.expect)(clack.log.warn).toHaveBeenCalledWith(vitest_1.expect.stringContaining('Failed to write MCP config'));
316
381
  (0, vitest_1.expect)(clackUtils.showCopyPasteInstructions).toHaveBeenCalled();
317
382
  });
318
383
  (0, vitest_1.it)('should handle mkdirSync errors', async () => {
319
384
  const { clack, clackUtils } = await getMocks();
320
- vitest_1.vi.mocked(clack.select)
321
- .mockResolvedValueOnce('yes')
322
- .mockResolvedValueOnce('cursor');
385
+ vitest_1.vi.mocked(clack.select).mockResolvedValueOnce('yes');
386
+ vitest_1.vi.mocked(clack.multiselect).mockResolvedValueOnce(['cursor']);
323
387
  vitest_1.vi.mocked(clackUtils.abortIfCancelled).mockImplementation((value) => Promise.resolve(value));
324
388
  const mockReadFile = vitest_1.vi
325
389
  .fn()
@@ -332,14 +396,13 @@ vitest_1.vi.mock('node:child_process');
332
396
  vitest_1.vi.spyOn(fs.promises, 'writeFile').mockImplementation(mockWriteFile);
333
397
  vitest_1.vi.spyOn(fs, 'mkdirSync').mockImplementation(mockMkdirSync);
334
398
  await (0, vitest_1.expect)((0, mcp_config_1.offerProjectScopedMcpConfig)()).resolves.toBeUndefined();
335
- (0, vitest_1.expect)(clack.log.warn).toHaveBeenCalledWith(vitest_1.expect.stringContaining('Failed to write MCP config automatically'));
399
+ (0, vitest_1.expect)(clack.log.warn).toHaveBeenCalledWith(vitest_1.expect.stringContaining('Failed to write MCP config'));
336
400
  (0, vitest_1.expect)(clackUtils.showCopyPasteInstructions).toHaveBeenCalled();
337
401
  });
338
402
  (0, vitest_1.it)('should create config with empty servers/mcpServers when existing config lacks them', async () => {
339
403
  const { clack, clackUtils } = await getMocks();
340
- vitest_1.vi.mocked(clack.select)
341
- .mockResolvedValueOnce('yes')
342
- .mockResolvedValueOnce('vscode');
404
+ vitest_1.vi.mocked(clack.select).mockResolvedValueOnce('yes');
405
+ vitest_1.vi.mocked(clack.multiselect).mockResolvedValueOnce(['vscode']);
343
406
  vitest_1.vi.mocked(clackUtils.abortIfCancelled).mockImplementation((value) => Promise.resolve(value));
344
407
  const existingConfig = JSON.stringify({
345
408
  otherProperty: 'value',
@@ -361,8 +424,8 @@ vitest_1.vi.mock('node:child_process');
361
424
  const { clack, clackUtils } = await getMocks();
362
425
  vitest_1.vi.mocked(clack.select)
363
426
  .mockResolvedValueOnce('yes')
364
- .mockResolvedValueOnce('jetbrains')
365
427
  .mockResolvedValueOnce(true); // For the clipboard copy prompt
428
+ vitest_1.vi.mocked(clack.multiselect).mockResolvedValueOnce(['jetbrains']);
366
429
  vitest_1.vi.mocked(clackUtils.abortIfCancelled).mockImplementation((value) => Promise.resolve(value));
367
430
  // Mock clipboard copy
368
431
  const mockSpawn = vitest_1.vi.fn().mockReturnValue({
@@ -393,8 +456,8 @@ vitest_1.vi.mock('node:child_process');
393
456
  const { clack, clackUtils } = await getMocks();
394
457
  vitest_1.vi.mocked(clack.select)
395
458
  .mockResolvedValueOnce('yes')
396
- .mockResolvedValueOnce('other')
397
459
  .mockResolvedValueOnce(true); // For the clipboard copy prompt
460
+ vitest_1.vi.mocked(clack.multiselect).mockResolvedValueOnce(['other']);
398
461
  vitest_1.vi.mocked(clackUtils.abortIfCancelled).mockImplementation((value) => Promise.resolve(value));
399
462
  // Mock clipboard copy failure to test fallback
400
463
  const mockSpawn = vitest_1.vi.fn().mockReturnValue({
@@ -426,8 +489,8 @@ vitest_1.vi.mock('node:child_process');
426
489
  const { clack, clackUtils } = await getMocks();
427
490
  vitest_1.vi.mocked(clack.select)
428
491
  .mockResolvedValueOnce('yes')
429
- .mockResolvedValueOnce('jetbrains')
430
492
  .mockResolvedValueOnce(true); // For clipboard copy prompt
493
+ vitest_1.vi.mocked(clack.multiselect).mockResolvedValueOnce(['jetbrains']);
431
494
  vitest_1.vi.mocked(clackUtils.abortIfCancelled).mockImplementation((value) => Promise.resolve(value));
432
495
  // Mock clipboard copy to throw error
433
496
  const mockSpawn = vitest_1.vi.fn().mockImplementation(() => {
@@ -450,8 +513,8 @@ vitest_1.vi.mock('node:child_process');
450
513
  const { clack, clackUtils } = await getMocks();
451
514
  vitest_1.vi.mocked(clack.select)
452
515
  .mockResolvedValueOnce('explain') // User selects "What is MCP?"
453
- .mockResolvedValueOnce(true) // User selects "Yes" after explanation
454
- .mockResolvedValueOnce('cursor'); // User selects Cursor
516
+ .mockResolvedValueOnce(true); // User selects "Yes" after explanation
517
+ vitest_1.vi.mocked(clack.multiselect).mockResolvedValueOnce(['cursor']); // User selects Cursor
455
518
  vitest_1.vi.mocked(clackUtils.abortIfCancelled).mockImplementation((value) => Promise.resolve(value));
456
519
  const mockReadFile = vitest_1.vi
457
520
  .fn()
@@ -477,8 +540,8 @@ vitest_1.vi.mock('node:child_process');
477
540
  const { clack, clackUtils } = await getMocks();
478
541
  vitest_1.vi.mocked(clack.select)
479
542
  .mockResolvedValueOnce('yes')
480
- .mockResolvedValueOnce('jetbrains')
481
543
  .mockResolvedValueOnce(false); // User declines to copy to clipboard
544
+ vitest_1.vi.mocked(clack.multiselect).mockResolvedValueOnce(['jetbrains']);
482
545
  vitest_1.vi.mocked(clackUtils.abortIfCancelled).mockImplementation((value) => Promise.resolve(value));
483
546
  const mockSpawn = vitest_1.vi.fn();
484
547
  vitest_1.vi.spyOn(childProcess, 'spawn').mockImplementation(mockSpawn);
@@ -511,8 +574,70 @@ vitest_1.vi.mock('node:child_process');
511
574
  message: 'Would you like to configure MCP for your IDE now?',
512
575
  }));
513
576
  // Should NOT proceed with editor selection
514
- (0, vitest_1.expect)(clack.select).not.toHaveBeenCalledWith(vitest_1.expect.objectContaining({
515
- message: 'Which editor do you want to configure?',
577
+ (0, vitest_1.expect)(clack.multiselect).not.toHaveBeenCalled();
578
+ });
579
+ (0, vitest_1.it)('should configure multiple editors when selected', async () => {
580
+ const { clack, clackUtils } = await getMocks();
581
+ vitest_1.vi.mocked(clack.select).mockResolvedValueOnce('yes');
582
+ vitest_1.vi.mocked(clack.multiselect).mockResolvedValueOnce([
583
+ 'cursor',
584
+ 'vscode',
585
+ 'claudeCode',
586
+ ]);
587
+ vitest_1.vi.mocked(clackUtils.abortIfCancelled).mockImplementation((value) => Promise.resolve(value));
588
+ const mockReadFile = vitest_1.vi
589
+ .fn()
590
+ .mockRejectedValue(new Error('File not found'));
591
+ const mockWriteFile = vitest_1.vi.fn().mockResolvedValue(undefined);
592
+ const mockMkdirSync = vitest_1.vi.fn();
593
+ vitest_1.vi.spyOn(fs.promises, 'readFile').mockImplementation(mockReadFile);
594
+ vitest_1.vi.spyOn(fs.promises, 'writeFile').mockImplementation(mockWriteFile);
595
+ vitest_1.vi.spyOn(fs, 'mkdirSync').mockImplementation(mockMkdirSync);
596
+ await (0, mcp_config_1.offerProjectScopedMcpConfig)();
597
+ // Should write config for all three editors
598
+ (0, vitest_1.expect)(mockWriteFile).toHaveBeenCalledTimes(3);
599
+ (0, vitest_1.expect)(mockWriteFile).toHaveBeenCalledWith(vitest_1.expect.stringContaining('.cursor/mcp.json'), vitest_1.expect.stringContaining('"mcpServers"'), 'utf8');
600
+ (0, vitest_1.expect)(mockWriteFile).toHaveBeenCalledWith(vitest_1.expect.stringContaining('.vscode/mcp.json'), vitest_1.expect.stringContaining('"servers"'), 'utf8');
601
+ (0, vitest_1.expect)(mockWriteFile).toHaveBeenCalledWith(vitest_1.expect.stringContaining('.mcp.json'), vitest_1.expect.stringContaining('"mcpServers"'), 'utf8');
602
+ // Should show success messages for each (twice per editor: filename + editor-specific message)
603
+ (0, vitest_1.expect)(clack.log.success).toHaveBeenCalledWith('Added project-scoped Sentry MCP configuration for Cursor.');
604
+ (0, vitest_1.expect)(clack.log.success).toHaveBeenCalledWith('Added project-scoped Sentry MCP configuration for VS Code.');
605
+ (0, vitest_1.expect)(clack.log.success).toHaveBeenCalledWith('Added project-scoped Sentry MCP configuration for Claude Code.');
606
+ });
607
+ (0, vitest_1.it)('should return early when no editors are selected', async () => {
608
+ const { clack, clackUtils } = await getMocks();
609
+ vitest_1.vi.mocked(clack.select).mockResolvedValueOnce('yes');
610
+ vitest_1.vi.mocked(clack.multiselect).mockResolvedValueOnce([]);
611
+ vitest_1.vi.mocked(clackUtils.abortIfCancelled).mockImplementation((value) => Promise.resolve(value));
612
+ const mockWriteFile = vitest_1.vi.fn();
613
+ vitest_1.vi.spyOn(fs.promises, 'writeFile').mockImplementation(mockWriteFile);
614
+ await (0, mcp_config_1.offerProjectScopedMcpConfig)();
615
+ (0, vitest_1.expect)(clack.log.info).toHaveBeenCalledWith('No editors selected. You can add MCP configuration later.');
616
+ (0, vitest_1.expect)(mockWriteFile).not.toHaveBeenCalled();
617
+ });
618
+ (0, vitest_1.it)('should handle mixed success and failure for multiple editors', async () => {
619
+ const { clack, clackUtils } = await getMocks();
620
+ vitest_1.vi.mocked(clack.select).mockResolvedValueOnce('yes');
621
+ vitest_1.vi.mocked(clack.multiselect).mockResolvedValueOnce(['cursor', 'vscode']);
622
+ vitest_1.vi.mocked(clackUtils.abortIfCancelled).mockImplementation((value) => Promise.resolve(value));
623
+ const mockReadFile = vitest_1.vi
624
+ .fn()
625
+ .mockRejectedValue(new Error('File not found'));
626
+ const mockWriteFile = vitest_1.vi
627
+ .fn()
628
+ .mockResolvedValueOnce(undefined) // Cursor succeeds
629
+ .mockRejectedValueOnce(new Error('Permission denied')); // VS Code fails
630
+ const mockMkdirSync = vitest_1.vi.fn();
631
+ vitest_1.vi.spyOn(fs.promises, 'readFile').mockImplementation(mockReadFile);
632
+ vitest_1.vi.spyOn(fs.promises, 'writeFile').mockImplementation(mockWriteFile);
633
+ vitest_1.vi.spyOn(fs, 'mkdirSync').mockImplementation(mockMkdirSync);
634
+ await (0, mcp_config_1.offerProjectScopedMcpConfig)();
635
+ // Cursor should succeed
636
+ (0, vitest_1.expect)(clack.log.success).toHaveBeenCalledWith(vitest_1.expect.stringContaining('.cursor/mcp.json'));
637
+ // VS Code should fail and show fallback
638
+ (0, vitest_1.expect)(clack.log.warn).toHaveBeenCalledWith(vitest_1.expect.stringContaining('Failed to write MCP config for vscode'));
639
+ (0, vitest_1.expect)(clackUtils.showCopyPasteInstructions).toHaveBeenCalledWith(vitest_1.expect.objectContaining({
640
+ filename: path.join('.vscode', 'mcp.json'),
516
641
  }));
517
642
  });
518
643
  });