@sentry/wizard 6.11.0 → 6.13.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 (245) hide show
  1. package/CHANGELOG.md +64 -0
  2. package/dist/bin.js +16 -1
  3. package/dist/bin.js.map +1 -1
  4. package/dist/e2e-tests/tests/angular-17.test.js +3 -4
  5. package/dist/e2e-tests/tests/angular-17.test.js.map +1 -1
  6. package/dist/e2e-tests/tests/angular-19.test.js +3 -4
  7. package/dist/e2e-tests/tests/angular-19.test.js.map +1 -1
  8. package/dist/e2e-tests/tests/cloudflare-worker.test.js +5 -0
  9. package/dist/e2e-tests/tests/cloudflare-worker.test.js.map +1 -1
  10. package/dist/e2e-tests/tests/flutter.test.js +60 -0
  11. package/dist/e2e-tests/tests/flutter.test.js.map +1 -1
  12. package/dist/e2e-tests/tests/help-message.test.js +8 -3
  13. package/dist/e2e-tests/tests/help-message.test.js.map +1 -1
  14. package/dist/e2e-tests/tests/nuxt-3.test.js +12 -6
  15. package/dist/e2e-tests/tests/nuxt-3.test.js.map +1 -1
  16. package/dist/e2e-tests/tests/nuxt-4.test.js +12 -6
  17. package/dist/e2e-tests/tests/nuxt-4.test.js.map +1 -1
  18. package/dist/e2e-tests/tests/pnpm-workspace.test.js +8 -4
  19. package/dist/e2e-tests/tests/pnpm-workspace.test.js.map +1 -1
  20. package/dist/e2e-tests/tests/react-router-instrumentation-api.test.js +96 -0
  21. package/dist/e2e-tests/tests/react-router-instrumentation-api.test.js.map +1 -0
  22. package/dist/e2e-tests/tests/react-router.test.js +6 -7
  23. package/dist/e2e-tests/tests/react-router.test.js.map +1 -1
  24. package/dist/e2e-tests/tests/remix.test.js +2 -4
  25. package/dist/e2e-tests/tests/remix.test.js.map +1 -1
  26. package/dist/e2e-tests/tests/sveltekit-hooks.test.js +24 -8
  27. package/dist/e2e-tests/tests/sveltekit-hooks.test.js.map +1 -1
  28. package/dist/e2e-tests/tests/sveltekit-tracing.test.js +8 -4
  29. package/dist/e2e-tests/tests/sveltekit-tracing.test.js.map +1 -1
  30. package/dist/lib/Constants.d.ts +1 -0
  31. package/dist/lib/Constants.js +5 -0
  32. package/dist/lib/Constants.js.map +1 -1
  33. package/dist/lib/Steps/Integrations/Electron.js +2 -2
  34. package/dist/lib/Steps/Integrations/Electron.js.map +1 -1
  35. package/dist/src/android/android-wizard.js +3 -0
  36. package/dist/src/android/android-wizard.js.map +1 -1
  37. package/dist/src/angular/codemods/main.d.ts +1 -1
  38. package/dist/src/angular/codemods/main.js +0 -1
  39. package/dist/src/angular/codemods/main.js.map +1 -1
  40. package/dist/src/apple/apple-wizard.js +2 -3
  41. package/dist/src/apple/apple-wizard.js.map +1 -1
  42. package/dist/src/apple/check-installed-cli.d.ts +1 -1
  43. package/dist/src/apple/check-installed-cli.js +13 -7
  44. package/dist/src/apple/check-installed-cli.js.map +1 -1
  45. package/dist/src/apple/code-tools.js +17 -3
  46. package/dist/src/apple/code-tools.js.map +1 -1
  47. package/dist/src/apple/configure-package-manager.js +18 -5
  48. package/dist/src/apple/configure-package-manager.js.map +1 -1
  49. package/dist/src/apple/configure-xcode-project.js +8 -1
  50. package/dist/src/apple/configure-xcode-project.js.map +1 -1
  51. package/dist/src/apple/lookup-xcode-project.d.ts +8 -5
  52. package/dist/src/apple/lookup-xcode-project.js +22 -17
  53. package/dist/src/apple/lookup-xcode-project.js.map +1 -1
  54. package/dist/src/apple/options.d.ts +5 -0
  55. package/dist/src/apple/options.js.map +1 -1
  56. package/dist/src/apple/sentry-swift-package.d.ts +4 -0
  57. package/dist/src/apple/sentry-swift-package.js +17 -0
  58. package/dist/src/apple/sentry-swift-package.js.map +1 -0
  59. package/dist/src/apple/snapshots/apple-snapshots-wizard.d.ts +2 -0
  60. package/dist/src/apple/snapshots/apple-snapshots-wizard.js +251 -0
  61. package/dist/src/apple/snapshots/apple-snapshots-wizard.js.map +1 -0
  62. package/dist/src/apple/snapshots/configure-snapshotpreviews-xcode-project.d.ts +13 -0
  63. package/dist/src/apple/snapshots/configure-snapshotpreviews-xcode-project.js +48 -0
  64. package/dist/src/apple/snapshots/configure-snapshotpreviews-xcode-project.js.map +1 -0
  65. package/dist/src/apple/snapshots/snapshot-test-file.d.ts +18 -0
  66. package/dist/src/apple/snapshots/snapshot-test-file.js +122 -0
  67. package/dist/src/apple/snapshots/snapshot-test-file.js.map +1 -0
  68. package/dist/src/apple/snapshots/snapshot-verification-scheme.d.ts +6 -0
  69. package/dist/src/apple/snapshots/snapshot-verification-scheme.js +147 -0
  70. package/dist/src/apple/snapshots/snapshot-verification-scheme.js.map +1 -0
  71. package/dist/src/apple/snapshots/snapshotpreviews-package.d.ts +4 -0
  72. package/dist/src/apple/snapshots/snapshotpreviews-package.js +8 -0
  73. package/dist/src/apple/snapshots/snapshotpreviews-package.js.map +1 -0
  74. package/dist/src/apple/snapshots/snapshots-cli-preflight.d.ts +23 -0
  75. package/dist/src/apple/snapshots/snapshots-cli-preflight.js +136 -0
  76. package/dist/src/apple/snapshots/snapshots-cli-preflight.js.map +1 -0
  77. package/dist/src/apple/xcode-manager.d.ts +59 -1
  78. package/dist/src/apple/xcode-manager.js +507 -106
  79. package/dist/src/apple/xcode-manager.js.map +1 -1
  80. package/dist/src/cloudflare/cloudflare-wizard.js +5 -0
  81. package/dist/src/cloudflare/cloudflare-wizard.js.map +1 -1
  82. package/dist/src/cloudflare/sdk-setup.d.ts +1 -0
  83. package/dist/src/cloudflare/sdk-setup.js.map +1 -1
  84. package/dist/src/cloudflare/templates.d.ts +1 -0
  85. package/dist/src/cloudflare/templates.js +7 -1
  86. package/dist/src/cloudflare/templates.js.map +1 -1
  87. package/dist/src/cloudflare/wrap-worker.d.ts +1 -0
  88. package/dist/src/cloudflare/wrap-worker.js +7 -0
  89. package/dist/src/cloudflare/wrap-worker.js.map +1 -1
  90. package/dist/src/flutter/flutter-wizard.js +3 -0
  91. package/dist/src/flutter/flutter-wizard.js.map +1 -1
  92. package/dist/src/nextjs/templates.js +12 -6
  93. package/dist/src/nextjs/templates.js.map +1 -1
  94. package/dist/src/nuxt/templates.js +12 -6
  95. package/dist/src/nuxt/templates.js.map +1 -1
  96. package/dist/src/react-native/expo.d.ts +6 -0
  97. package/dist/src/react-native/expo.js +27 -1
  98. package/dist/src/react-native/expo.js.map +1 -1
  99. package/dist/src/react-native/git.d.ts +5 -0
  100. package/dist/src/react-native/git.js +32 -1
  101. package/dist/src/react-native/git.js.map +1 -1
  102. package/dist/src/react-native/javascript.js +3 -1
  103. package/dist/src/react-native/javascript.js.map +1 -1
  104. package/dist/src/react-native/react-native-wizard.js +12 -6
  105. package/dist/src/react-native/react-native-wizard.js.map +1 -1
  106. package/dist/src/react-router/codemods/client.entry.d.ts +1 -1
  107. package/dist/src/react-router/codemods/client.entry.js +124 -26
  108. package/dist/src/react-router/codemods/client.entry.js.map +1 -1
  109. package/dist/src/react-router/codemods/react-router-config.js +1 -1
  110. package/dist/src/react-router/codemods/react-router-config.js.map +1 -1
  111. package/dist/src/react-router/codemods/server-entry.d.ts +1 -1
  112. package/dist/src/react-router/codemods/server-entry.js +40 -4
  113. package/dist/src/react-router/codemods/server-entry.js.map +1 -1
  114. package/dist/src/react-router/codemods/vite.js +46 -1
  115. package/dist/src/react-router/codemods/vite.js.map +1 -1
  116. package/dist/src/react-router/react-router-wizard.js +62 -21
  117. package/dist/src/react-router/react-router-wizard.js.map +1 -1
  118. package/dist/src/react-router/sdk-setup.d.ts +5 -3
  119. package/dist/src/react-router/sdk-setup.js +44 -16
  120. package/dist/src/react-router/sdk-setup.js.map +1 -1
  121. package/dist/src/react-router/templates.d.ts +2 -4
  122. package/dist/src/react-router/templates.js +89 -87
  123. package/dist/src/react-router/templates.js.map +1 -1
  124. package/dist/src/remix/sdk-setup.js +1 -2
  125. package/dist/src/remix/sdk-setup.js.map +1 -1
  126. package/dist/src/run.d.ts +4 -1
  127. package/dist/src/run.js +13 -0
  128. package/dist/src/run.js.map +1 -1
  129. package/dist/src/sourcemaps/tools/remix.js +4 -4
  130. package/dist/src/sourcemaps/tools/remix.js.map +1 -1
  131. package/dist/src/sourcemaps/tools/vite.js +1 -1
  132. package/dist/src/sourcemaps/tools/vite.js.map +1 -1
  133. package/dist/src/sveltekit/sdk-setup/setup.js +17 -4
  134. package/dist/src/sveltekit/sdk-setup/setup.js.map +1 -1
  135. package/dist/src/sveltekit/sdk-setup/vite.js +1 -1
  136. package/dist/src/sveltekit/sdk-setup/vite.js.map +1 -1
  137. package/dist/src/sveltekit/templates.js +12 -6
  138. package/dist/src/sveltekit/templates.js.map +1 -1
  139. package/dist/src/utils/ast-utils.d.ts +10 -0
  140. package/dist/src/utils/ast-utils.js +19 -1
  141. package/dist/src/utils/ast-utils.js.map +1 -1
  142. package/dist/src/utils/clack/index.d.ts +2 -1
  143. package/dist/src/utils/clack/index.js +17 -6
  144. package/dist/src/utils/clack/index.js.map +1 -1
  145. package/dist/src/utils/files.d.ts +2 -0
  146. package/dist/src/utils/files.js +58 -0
  147. package/dist/src/utils/files.js.map +1 -0
  148. package/dist/src/utils/git.d.ts +3 -1
  149. package/dist/src/utils/git.js +2 -1
  150. package/dist/src/utils/git.js.map +1 -1
  151. package/dist/src/utils/line-endings.d.ts +1 -0
  152. package/dist/src/utils/line-endings.js +76 -0
  153. package/dist/src/utils/line-endings.js.map +1 -0
  154. package/dist/src/version.d.ts +1 -1
  155. package/dist/src/version.js +1 -1
  156. package/dist/src/version.js.map +1 -1
  157. package/dist/test/angular/angular-wizard.test.js +0 -5
  158. package/dist/test/angular/angular-wizard.test.js.map +1 -1
  159. package/dist/test/apple/code-tools.test.js +78 -0
  160. package/dist/test/apple/code-tools.test.js.map +1 -1
  161. package/dist/test/apple/configure-package-manager.test.d.ts +1 -0
  162. package/dist/test/apple/configure-package-manager.test.js +161 -0
  163. package/dist/test/apple/configure-package-manager.test.js.map +1 -0
  164. package/dist/test/apple/lookup-xcode-project.test.d.ts +1 -0
  165. package/dist/test/apple/lookup-xcode-project.test.js +167 -0
  166. package/dist/test/apple/lookup-xcode-project.test.js.map +1 -0
  167. package/dist/test/apple/snapshots/apple-snapshots-wizard.test.d.ts +1 -0
  168. package/dist/test/apple/snapshots/apple-snapshots-wizard.test.js +487 -0
  169. package/dist/test/apple/snapshots/apple-snapshots-wizard.test.js.map +1 -0
  170. package/dist/test/apple/snapshots/hosted-test-target-fixture.d.ts +24 -0
  171. package/dist/test/apple/snapshots/hosted-test-target-fixture.js +191 -0
  172. package/dist/test/apple/snapshots/hosted-test-target-fixture.js.map +1 -0
  173. package/dist/test/apple/snapshots/snapshot-test-file.test.d.ts +1 -0
  174. package/dist/test/apple/snapshots/snapshot-test-file.test.js +110 -0
  175. package/dist/test/apple/snapshots/snapshot-test-file.test.js.map +1 -0
  176. package/dist/test/apple/snapshots/snapshot-verification-scheme.test.d.ts +1 -0
  177. package/dist/test/apple/snapshots/snapshot-verification-scheme.test.js +146 -0
  178. package/dist/test/apple/snapshots/snapshot-verification-scheme.test.js.map +1 -0
  179. package/dist/test/apple/snapshots/snapshotpreviews-xcode-smoke.test.d.ts +1 -0
  180. package/dist/test/apple/snapshots/snapshotpreviews-xcode-smoke.test.js +186 -0
  181. package/dist/test/apple/snapshots/snapshotpreviews-xcode-smoke.test.js.map +1 -0
  182. package/dist/test/apple/snapshots/snapshots-cli-preflight.test.d.ts +1 -0
  183. package/dist/test/apple/snapshots/snapshots-cli-preflight.test.js +192 -0
  184. package/dist/test/apple/snapshots/snapshots-cli-preflight.test.js.map +1 -0
  185. package/dist/test/apple/snapshots/source-file-insertion.test.d.ts +1 -0
  186. package/dist/test/apple/snapshots/source-file-insertion.test.js +77 -0
  187. package/dist/test/apple/snapshots/source-file-insertion.test.js.map +1 -0
  188. package/dist/test/apple/xcode-manager.test.js +452 -43
  189. package/dist/test/apple/xcode-manager.test.js.map +1 -1
  190. package/dist/test/cloudflare/sdk-setup.test.js +20 -2
  191. package/dist/test/cloudflare/sdk-setup.test.js.map +1 -1
  192. package/dist/test/cloudflare/templates.test.js +54 -0
  193. package/dist/test/cloudflare/templates.test.js.map +1 -1
  194. package/dist/test/cloudflare/wrap-worker.test.js +74 -11
  195. package/dist/test/cloudflare/wrap-worker.test.js.map +1 -1
  196. package/dist/test/constants.test.d.ts +1 -0
  197. package/dist/test/constants.test.js +12 -0
  198. package/dist/test/constants.test.js.map +1 -0
  199. package/dist/test/nextjs/templates.test.js +66 -33
  200. package/dist/test/nextjs/templates.test.js.map +1 -1
  201. package/dist/test/nuxt/templates.test.js +66 -36
  202. package/dist/test/nuxt/templates.test.js.map +1 -1
  203. package/dist/test/react-native/expo.test.js +140 -0
  204. package/dist/test/react-native/expo.test.js.map +1 -1
  205. package/dist/test/react-native/git.test.d.ts +1 -0
  206. package/dist/test/react-native/git.test.js +160 -0
  207. package/dist/test/react-native/git.test.js.map +1 -0
  208. package/dist/test/react-router/codemods/client-entry.test.js +38 -5
  209. package/dist/test/react-router/codemods/client-entry.test.js.map +1 -1
  210. package/dist/test/react-router/codemods/server-entry.test.js +83 -0
  211. package/dist/test/react-router/codemods/server-entry.test.js.map +1 -1
  212. package/dist/test/react-router/codemods/vite.test.js +89 -0
  213. package/dist/test/react-router/codemods/vite.test.js.map +1 -1
  214. package/dist/test/react-router/sdk-setup.test.js +98 -6
  215. package/dist/test/react-router/sdk-setup.test.js.map +1 -1
  216. package/dist/test/react-router/templates.test.js +50 -38
  217. package/dist/test/react-router/templates.test.js.map +1 -1
  218. package/dist/test/remix/build-script.test.d.ts +1 -0
  219. package/dist/test/remix/build-script.test.js +124 -0
  220. package/dist/test/remix/build-script.test.js.map +1 -0
  221. package/dist/test/remix/client-entry.test.js +4 -10
  222. package/dist/test/remix/client-entry.test.js.map +1 -1
  223. package/dist/test/run.test.d.ts +1 -0
  224. package/dist/test/run.test.js +137 -0
  225. package/dist/test/run.test.js.map +1 -0
  226. package/dist/test/sourcemaps/tools/vite.test.js +12 -8
  227. package/dist/test/sourcemaps/tools/vite.test.js.map +1 -1
  228. package/dist/test/sveltekit/templates.test.js +78 -27
  229. package/dist/test/sveltekit/templates.test.js.map +1 -1
  230. package/dist/test/utils/ast-utils.test.js +22 -0
  231. package/dist/test/utils/ast-utils.test.js.map +1 -1
  232. package/dist/test/utils/clack/index.test.js +101 -0
  233. package/dist/test/utils/clack/index.test.js.map +1 -1
  234. package/dist/test/utils/git.test.js +10 -0
  235. package/dist/test/utils/git.test.js.map +1 -1
  236. package/dist/test/utils/line-endings.test.d.ts +1 -0
  237. package/dist/test/utils/line-endings.test.js +103 -0
  238. package/dist/test/utils/line-endings.test.js.map +1 -0
  239. package/package.json +2 -2
  240. package/dist/src/react-router/codemods/root.d.ts +0 -1
  241. package/dist/src/react-router/codemods/root.js +0 -171
  242. package/dist/src/react-router/codemods/root.js.map +0 -1
  243. package/dist/test/react-router/codemods/root.test.js +0 -178
  244. package/dist/test/react-router/codemods/root.test.js.map +0 -1
  245. /package/dist/{test/react-router/codemods/root.test.d.ts → e2e-tests/tests/react-router-instrumentation-api.test.d.ts} +0 -0
@@ -0,0 +1,161 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ const Sentry = __importStar(require("@sentry/node"));
30
+ const fs = __importStar(require("fs"));
31
+ const os = __importStar(require("os"));
32
+ const path = __importStar(require("path"));
33
+ const cocoapod = __importStar(require("../../src/apple/cocoapod"));
34
+ const configure_package_manager_1 = require("../../src/apple/configure-package-manager");
35
+ // @ts-expect-error - clack is ESM and TS complains about that. It works though
36
+ const prompts_1 = __importDefault(require("@clack/prompts"));
37
+ const vitest_1 = require("vitest");
38
+ vitest_1.vi.mock('@clack/prompts', () => ({
39
+ __esModule: true,
40
+ default: {
41
+ log: {
42
+ warn: vitest_1.vi.fn(),
43
+ step: vitest_1.vi.fn(),
44
+ },
45
+ select: vitest_1.vi.fn(),
46
+ },
47
+ }));
48
+ vitest_1.vi.mock('../../src/apple/cocoapod');
49
+ vitest_1.vi.mock('../../src/utils/clack', () => ({
50
+ abortIfCancelled: vitest_1.vi.fn((value) => Promise.resolve(value)),
51
+ }));
52
+ vitest_1.vi.mock('../../src/telemetry', () => ({
53
+ traceStep: vitest_1.vi.fn(async (_name, fn) => await fn()),
54
+ }));
55
+ vitest_1.vi.mock('../../src/utils/debug', () => ({
56
+ debug: vitest_1.vi.fn(),
57
+ }));
58
+ vitest_1.vi.mock('@sentry/node', async () => {
59
+ const actual = await vitest_1.vi.importActual('@sentry/node');
60
+ return {
61
+ ...actual,
62
+ setTag: vitest_1.vi.fn(),
63
+ captureException: vitest_1.vi.fn(() => 'id'),
64
+ };
65
+ });
66
+ (0, vitest_1.describe)('configurePackageManager', () => {
67
+ let projectDir;
68
+ (0, vitest_1.beforeEach)(() => {
69
+ projectDir = fs.mkdtempSync(path.join(os.tmpdir(), 'test-project'));
70
+ vitest_1.vi.clearAllMocks();
71
+ });
72
+ (0, vitest_1.afterEach)(() => {
73
+ vitest_1.vi.clearAllMocks();
74
+ });
75
+ (0, vitest_1.describe)('when CocoaPods is not available', () => {
76
+ (0, vitest_1.it)('should default to SPM and not prompt user', async () => {
77
+ // -- Arrange --
78
+ vitest_1.vi.spyOn(cocoapod, 'usesCocoaPod').mockReturnValue(false);
79
+ // -- Act --
80
+ const result = await (0, configure_package_manager_1.configurePackageManager)({ projectDir });
81
+ // -- Assert --
82
+ (0, vitest_1.expect)(result.shouldUseSPM).toBe(true);
83
+ (0, vitest_1.expect)(prompts_1.default.select).not.toHaveBeenCalled();
84
+ (0, vitest_1.expect)(prompts_1.default.log.warn).not.toHaveBeenCalled();
85
+ (0, vitest_1.expect)(Sentry.setTag).toHaveBeenCalledWith('cocoapod-exists', false);
86
+ (0, vitest_1.expect)(Sentry.setTag).toHaveBeenCalledWith('package-manager', 'SPM');
87
+ });
88
+ });
89
+ (0, vitest_1.describe)('when CocoaPods is available', () => {
90
+ (0, vitest_1.beforeEach)(() => {
91
+ vitest_1.vi.spyOn(cocoapod, 'usesCocoaPod').mockReturnValue(true);
92
+ });
93
+ (0, vitest_1.it)('should show deprecation warning', async () => {
94
+ // -- Arrange --
95
+ vitest_1.vi.mocked(prompts_1.default.select).mockResolvedValue('SPM');
96
+ // -- Act --
97
+ await (0, configure_package_manager_1.configurePackageManager)({ projectDir });
98
+ // -- Assert --
99
+ (0, vitest_1.expect)(prompts_1.default.log.warn).toHaveBeenCalledWith('CocoaPods is being deprecated. No new updates will be released after June 2026.\nWe recommend migrating to Swift Package Manager (SPM).');
100
+ });
101
+ (0, vitest_1.it)('should prompt user to choose package manager', async () => {
102
+ // -- Arrange --
103
+ vitest_1.vi.mocked(prompts_1.default.select).mockResolvedValue('SPM');
104
+ // -- Act --
105
+ await (0, configure_package_manager_1.configurePackageManager)({ projectDir });
106
+ // -- Assert --
107
+ (0, vitest_1.expect)(prompts_1.default.select).toHaveBeenCalledWith({
108
+ message: 'Which package manager would you like to use to add Sentry?',
109
+ options: [
110
+ {
111
+ value: 'SPM',
112
+ label: 'Swift Package Manager',
113
+ hint: 'Recommended',
114
+ },
115
+ {
116
+ value: 'CocoaPods',
117
+ label: 'CocoaPods',
118
+ hint: 'Deprecated - no updates after June 2026',
119
+ },
120
+ ],
121
+ });
122
+ });
123
+ (0, vitest_1.it)('should use SPM when user selects SPM', async () => {
124
+ // -- Arrange --
125
+ vitest_1.vi.mocked(prompts_1.default.select).mockResolvedValue('SPM');
126
+ // -- Act --
127
+ const result = await (0, configure_package_manager_1.configurePackageManager)({ projectDir });
128
+ // -- Assert --
129
+ (0, vitest_1.expect)(result.shouldUseSPM).toBe(true);
130
+ (0, vitest_1.expect)(cocoapod.addCocoaPods).not.toHaveBeenCalled();
131
+ (0, vitest_1.expect)(Sentry.setTag).toHaveBeenCalledWith('cocoapod-exists', true);
132
+ (0, vitest_1.expect)(Sentry.setTag).toHaveBeenCalledWith('package-manager', 'SPM');
133
+ });
134
+ (0, vitest_1.it)('should use CocoaPods when user selects CocoaPods', async () => {
135
+ // -- Arrange --
136
+ vitest_1.vi.mocked(prompts_1.default.select).mockResolvedValue('CocoaPods');
137
+ vitest_1.vi.spyOn(cocoapod, 'addCocoaPods').mockResolvedValue(true);
138
+ // -- Act --
139
+ const result = await (0, configure_package_manager_1.configurePackageManager)({ projectDir });
140
+ // -- Assert --
141
+ (0, vitest_1.expect)(result.shouldUseSPM).toBe(false);
142
+ (0, vitest_1.expect)(cocoapod.addCocoaPods).toHaveBeenCalledWith(projectDir);
143
+ (0, vitest_1.expect)(Sentry.setTag).toHaveBeenCalledWith('cocoapod-exists', true);
144
+ (0, vitest_1.expect)(Sentry.setTag).toHaveBeenCalledWith('cocoapod-added', true);
145
+ (0, vitest_1.expect)(Sentry.setTag).toHaveBeenCalledWith('package-manager', 'CocoaPods');
146
+ });
147
+ (0, vitest_1.it)('should handle CocoaPods addition failure', async () => {
148
+ // -- Arrange --
149
+ vitest_1.vi.mocked(prompts_1.default.select).mockResolvedValue('CocoaPods');
150
+ vitest_1.vi.spyOn(cocoapod, 'addCocoaPods').mockResolvedValue(false);
151
+ // -- Act --
152
+ const result = await (0, configure_package_manager_1.configurePackageManager)({ projectDir });
153
+ // -- Assert --
154
+ (0, vitest_1.expect)(result.shouldUseSPM).toBe(false);
155
+ (0, vitest_1.expect)(cocoapod.addCocoaPods).toHaveBeenCalledWith(projectDir);
156
+ (0, vitest_1.expect)(Sentry.setTag).toHaveBeenCalledWith('cocoapod-added', false);
157
+ (0, vitest_1.expect)(Sentry.setTag).toHaveBeenCalledWith('package-manager', 'CocoaPods');
158
+ });
159
+ });
160
+ });
161
+ //# sourceMappingURL=configure-package-manager.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"configure-package-manager.test.js","sourceRoot":"","sources":["../../../test/apple/configure-package-manager.test.ts"],"names":[],"mappings":"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","sourcesContent":["import * as Sentry from '@sentry/node';\nimport * as fs from 'fs';\nimport * as os from 'os';\nimport * as path from 'path';\nimport * as cocoapod from '../../src/apple/cocoapod';\nimport { configurePackageManager } from '../../src/apple/configure-package-manager';\n// @ts-expect-error - clack is ESM and TS complains about that. It works though\nimport clack from '@clack/prompts';\nimport { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';\n\nvi.mock('@clack/prompts', () => ({\n __esModule: true,\n default: {\n log: {\n warn: vi.fn(),\n step: vi.fn(),\n },\n select: vi.fn(),\n },\n}));\n\nvi.mock('../../src/apple/cocoapod');\nvi.mock('../../src/utils/clack', () => ({\n abortIfCancelled: vi.fn((value: unknown) => Promise.resolve(value)),\n}));\n\nvi.mock('../../src/telemetry', () => ({\n traceStep: vi.fn(\n async (_name: string, fn: () => Promise<unknown>) => await fn(),\n ),\n}));\n\nvi.mock('../../src/utils/debug', () => ({\n debug: vi.fn(),\n}));\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 setTag: vi.fn(),\n captureException: vi.fn(() => 'id'),\n };\n});\n\ndescribe('configurePackageManager', () => {\n let projectDir: string;\n\n beforeEach(() => {\n projectDir = fs.mkdtempSync(path.join(os.tmpdir(), 'test-project'));\n vi.clearAllMocks();\n });\n\n afterEach(() => {\n vi.clearAllMocks();\n });\n\n describe('when CocoaPods is not available', () => {\n it('should default to SPM and not prompt user', async () => {\n // -- Arrange --\n vi.spyOn(cocoapod, 'usesCocoaPod').mockReturnValue(false);\n\n // -- Act --\n const result = await configurePackageManager({ projectDir });\n\n // -- Assert --\n expect(result.shouldUseSPM).toBe(true);\n expect(clack.select).not.toHaveBeenCalled();\n expect(clack.log.warn).not.toHaveBeenCalled();\n expect(Sentry.setTag).toHaveBeenCalledWith('cocoapod-exists', false);\n expect(Sentry.setTag).toHaveBeenCalledWith('package-manager', 'SPM');\n });\n });\n\n describe('when CocoaPods is available', () => {\n beforeEach(() => {\n vi.spyOn(cocoapod, 'usesCocoaPod').mockReturnValue(true);\n });\n\n it('should show deprecation warning', async () => {\n // -- Arrange --\n vi.mocked(clack.select).mockResolvedValue('SPM' as never);\n\n // -- Act --\n await configurePackageManager({ projectDir });\n\n // -- Assert --\n expect(clack.log.warn).toHaveBeenCalledWith(\n 'CocoaPods is being deprecated. No new updates will be released after June 2026.\\nWe recommend migrating to Swift Package Manager (SPM).',\n );\n });\n\n it('should prompt user to choose package manager', async () => {\n // -- Arrange --\n vi.mocked(clack.select).mockResolvedValue('SPM' as never);\n\n // -- Act --\n await configurePackageManager({ projectDir });\n\n // -- Assert --\n expect(clack.select).toHaveBeenCalledWith({\n message: 'Which package manager would you like to use to add Sentry?',\n options: [\n {\n value: 'SPM',\n label: 'Swift Package Manager',\n hint: 'Recommended',\n },\n {\n value: 'CocoaPods',\n label: 'CocoaPods',\n hint: 'Deprecated - no updates after June 2026',\n },\n ],\n });\n });\n\n it('should use SPM when user selects SPM', async () => {\n // -- Arrange --\n vi.mocked(clack.select).mockResolvedValue('SPM' as never);\n\n // -- Act --\n const result = await configurePackageManager({ projectDir });\n\n // -- Assert --\n expect(result.shouldUseSPM).toBe(true);\n expect(cocoapod.addCocoaPods).not.toHaveBeenCalled();\n expect(Sentry.setTag).toHaveBeenCalledWith('cocoapod-exists', true);\n expect(Sentry.setTag).toHaveBeenCalledWith('package-manager', 'SPM');\n });\n\n it('should use CocoaPods when user selects CocoaPods', async () => {\n // -- Arrange --\n vi.mocked(clack.select).mockResolvedValue('CocoaPods' as never);\n vi.spyOn(cocoapod, 'addCocoaPods').mockResolvedValue(true);\n\n // -- Act --\n const result = await configurePackageManager({ projectDir });\n\n // -- Assert --\n expect(result.shouldUseSPM).toBe(false);\n expect(cocoapod.addCocoaPods).toHaveBeenCalledWith(projectDir);\n expect(Sentry.setTag).toHaveBeenCalledWith('cocoapod-exists', true);\n expect(Sentry.setTag).toHaveBeenCalledWith('cocoapod-added', true);\n expect(Sentry.setTag).toHaveBeenCalledWith(\n 'package-manager',\n 'CocoaPods',\n );\n });\n\n it('should handle CocoaPods addition failure', async () => {\n // -- Arrange --\n vi.mocked(clack.select).mockResolvedValue('CocoaPods' as never);\n vi.spyOn(cocoapod, 'addCocoaPods').mockResolvedValue(false);\n\n // -- Act --\n const result = await configurePackageManager({ projectDir });\n\n // -- Assert --\n expect(result.shouldUseSPM).toBe(false);\n expect(cocoapod.addCocoaPods).toHaveBeenCalledWith(projectDir);\n expect(Sentry.setTag).toHaveBeenCalledWith('cocoapod-added', false);\n expect(Sentry.setTag).toHaveBeenCalledWith(\n 'package-manager',\n 'CocoaPods',\n );\n });\n });\n});\n"]}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,167 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ const fs = __importStar(require("node:fs"));
27
+ const os = __importStar(require("node:os"));
28
+ const path = __importStar(require("node:path"));
29
+ const vitest_1 = require("vitest");
30
+ const mocks = vitest_1.vi.hoisted(() => {
31
+ const targetsByProjectPath = new Map();
32
+ return {
33
+ abort: vitest_1.vi.fn(() => {
34
+ throw new Error('abort');
35
+ }),
36
+ askForItemSelection: vitest_1.vi.fn(),
37
+ clackError: vitest_1.vi.fn(),
38
+ debug: vitest_1.vi.fn(),
39
+ searchXcodeProjectAtPath: vitest_1.vi.fn(),
40
+ setTag: vitest_1.vi.fn(),
41
+ targetsByProjectPath,
42
+ traceStep: vitest_1.vi.fn(async (_name, callback) => await callback()),
43
+ XcodeProject: vitest_1.vi.fn(function (projectPath) {
44
+ this.projectPath = projectPath;
45
+ this.xcodeprojPath = path.dirname(projectPath);
46
+ this.getAllTargets = () => targetsByProjectPath.get(projectPath) ?? [];
47
+ }),
48
+ };
49
+ });
50
+ vitest_1.vi.mock('@clack/prompts', () => ({
51
+ default: {
52
+ log: {
53
+ error: mocks.clackError,
54
+ },
55
+ },
56
+ }));
57
+ vitest_1.vi.mock('@sentry/node', () => ({
58
+ setTag: mocks.setTag,
59
+ }));
60
+ vitest_1.vi.mock('../../src/apple/search-xcode-project-at-path', () => ({
61
+ searchXcodeProjectAtPath: mocks.searchXcodeProjectAtPath,
62
+ }));
63
+ vitest_1.vi.mock('../../src/apple/xcode-manager', () => ({
64
+ XcodeProject: mocks.XcodeProject,
65
+ }));
66
+ vitest_1.vi.mock('../../src/telemetry', () => ({
67
+ traceStep: mocks.traceStep,
68
+ }));
69
+ vitest_1.vi.mock('../../src/utils/clack', () => ({
70
+ abort: mocks.abort,
71
+ askForItemSelection: mocks.askForItemSelection,
72
+ }));
73
+ vitest_1.vi.mock('../../src/utils/debug', () => ({
74
+ debug: mocks.debug,
75
+ }));
76
+ const lookup_xcode_project_1 = require("../../src/apple/lookup-xcode-project");
77
+ function createProject(projectDir, projectName) {
78
+ const projectPath = path.join(projectDir, projectName);
79
+ fs.mkdirSync(projectPath, { recursive: true });
80
+ const pbxprojPath = path.join(projectPath, 'project.pbxproj');
81
+ fs.writeFileSync(pbxprojPath, 'mock pbxproj');
82
+ return pbxprojPath;
83
+ }
84
+ function createMockXcodeProject(pbxprojPath) {
85
+ const XcodeProjectConstructor = mocks.XcodeProject;
86
+ return new XcodeProjectConstructor(pbxprojPath);
87
+ }
88
+ (0, vitest_1.describe)('lookup-xcode-project', () => {
89
+ let projectDir;
90
+ (0, vitest_1.beforeEach)(() => {
91
+ projectDir = fs.mkdtempSync(path.join(os.tmpdir(), 'lookup-xcode-project-'));
92
+ vitest_1.vi.clearAllMocks();
93
+ mocks.targetsByProjectPath.clear();
94
+ });
95
+ (0, vitest_1.afterEach)(() => {
96
+ fs.rmSync(projectDir, { force: true, recursive: true });
97
+ });
98
+ (0, vitest_1.describe)('lookupXcodeProject', () => {
99
+ (0, vitest_1.it)('returns an Xcode project without selecting a target', async () => {
100
+ const pbxprojPath = createProject(projectDir, 'App.xcodeproj');
101
+ mocks.searchXcodeProjectAtPath.mockReturnValue(['App.xcodeproj']);
102
+ mocks.targetsByProjectPath.set(pbxprojPath, ['App']);
103
+ const result = await (0, lookup_xcode_project_1.lookupXcodeProject)({ projectDir });
104
+ (0, vitest_1.expect)(mocks.searchXcodeProjectAtPath).toHaveBeenCalledWith(projectDir);
105
+ (0, vitest_1.expect)(mocks.XcodeProject).toHaveBeenCalledWith(pbxprojPath);
106
+ (0, vitest_1.expect)(result).toEqual(vitest_1.expect.objectContaining({ projectPath: pbxprojPath }));
107
+ (0, vitest_1.expect)(mocks.askForItemSelection).not.toHaveBeenCalledWith(['App'], 'Which target do you want to add Sentry to?');
108
+ });
109
+ (0, vitest_1.it)('prompts when multiple Xcode projects are found', async () => {
110
+ createProject(projectDir, 'First.xcodeproj');
111
+ const selectedPbxprojPath = createProject(projectDir, 'Second.xcodeproj');
112
+ mocks.searchXcodeProjectAtPath.mockReturnValue([
113
+ 'First.xcodeproj',
114
+ 'Second.xcodeproj',
115
+ ]);
116
+ mocks.askForItemSelection.mockResolvedValue({
117
+ value: 'Second.xcodeproj',
118
+ });
119
+ const result = await (0, lookup_xcode_project_1.lookupXcodeProject)({ projectDir });
120
+ (0, vitest_1.expect)(mocks.askForItemSelection).toHaveBeenCalledWith(['First.xcodeproj', 'Second.xcodeproj'], 'Which project do you want to add Sentry to?');
121
+ (0, vitest_1.expect)(result).toEqual(vitest_1.expect.objectContaining({ projectPath: selectedPbxprojPath }));
122
+ });
123
+ (0, vitest_1.it)('fails instead of prompting when multiple Xcode projects are found in non-interactive mode', async () => {
124
+ createProject(projectDir, 'First.xcodeproj');
125
+ createProject(projectDir, 'Second.xcodeproj');
126
+ mocks.searchXcodeProjectAtPath.mockReturnValue([
127
+ 'First.xcodeproj',
128
+ 'Second.xcodeproj',
129
+ ]);
130
+ await (0, vitest_1.expect)((0, lookup_xcode_project_1.lookupXcodeProject)({ projectDir, nonInteractive: true })).rejects.toThrow('abort');
131
+ (0, vitest_1.expect)(mocks.askForItemSelection).not.toHaveBeenCalled();
132
+ (0, vitest_1.expect)(mocks.clackError).toHaveBeenCalledWith(vitest_1.expect.stringContaining('Multiple Xcode projects found'));
133
+ });
134
+ });
135
+ (0, vitest_1.describe)('selectXcodeTarget', () => {
136
+ (0, vitest_1.it)('returns the only target without prompting', async () => {
137
+ const pbxprojPath = createProject(projectDir, 'App.xcodeproj');
138
+ mocks.targetsByProjectPath.set(pbxprojPath, ['App']);
139
+ const xcProject = createMockXcodeProject(pbxprojPath);
140
+ const result = await (0, lookup_xcode_project_1.selectXcodeTarget)(xcProject);
141
+ (0, vitest_1.expect)(result).toBe('App');
142
+ (0, vitest_1.expect)(mocks.askForItemSelection).not.toHaveBeenCalled();
143
+ });
144
+ (0, vitest_1.it)('prompts when multiple targets are available', async () => {
145
+ const pbxprojPath = createProject(projectDir, 'App.xcodeproj');
146
+ mocks.targetsByProjectPath.set(pbxprojPath, ['App', 'Widget']);
147
+ mocks.askForItemSelection.mockResolvedValue({ value: 'Widget' });
148
+ const xcProject = createMockXcodeProject(pbxprojPath);
149
+ const result = await (0, lookup_xcode_project_1.selectXcodeTarget)(xcProject);
150
+ (0, vitest_1.expect)(mocks.askForItemSelection).toHaveBeenCalledWith(['App', 'Widget'], 'Which target do you want to add Sentry to?');
151
+ (0, vitest_1.expect)(result).toBe('Widget');
152
+ });
153
+ (0, vitest_1.it)('selects from custom target candidates', async () => {
154
+ const pbxprojPath = createProject(projectDir, 'App.xcodeproj');
155
+ mocks.targetsByProjectPath.set(pbxprojPath, ['App']);
156
+ mocks.askForItemSelection.mockResolvedValue({ value: 'AppUITests' });
157
+ const xcProject = createMockXcodeProject(pbxprojPath);
158
+ const result = await (0, lookup_xcode_project_1.selectXcodeTarget)(xcProject, {
159
+ targetNames: ['AppTests', 'AppUITests'],
160
+ promptMessage: 'Which test target should render SnapshotPreviews?',
161
+ });
162
+ (0, vitest_1.expect)(mocks.askForItemSelection).toHaveBeenCalledWith(['AppTests', 'AppUITests'], 'Which test target should render SnapshotPreviews?');
163
+ (0, vitest_1.expect)(result).toBe('AppUITests');
164
+ });
165
+ });
166
+ });
167
+ //# sourceMappingURL=lookup-xcode-project.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lookup-xcode-project.test.js","sourceRoot":"","sources":["../../../test/apple/lookup-xcode-project.test.ts"],"names":[],"mappings":"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","sourcesContent":["import * as fs from 'node:fs';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';\n\ntype MockXcodeProject = {\n projectPath: string;\n xcodeprojPath: string;\n getAllTargets: () => string[];\n};\n\nconst mocks = vi.hoisted(() => {\n const targetsByProjectPath = new Map<string, string[]>();\n\n return {\n abort: vi.fn(() => {\n throw new Error('abort');\n }),\n askForItemSelection: vi.fn(),\n clackError: vi.fn(),\n debug: vi.fn(),\n searchXcodeProjectAtPath: vi.fn(),\n setTag: vi.fn(),\n targetsByProjectPath,\n traceStep: vi.fn(\n async <T>(_name: string, callback: () => Promise<T> | T): Promise<T> =>\n await callback(),\n ),\n XcodeProject: vi.fn(function (this: MockXcodeProject, projectPath: string) {\n this.projectPath = projectPath;\n this.xcodeprojPath = path.dirname(projectPath);\n this.getAllTargets = () => targetsByProjectPath.get(projectPath) ?? [];\n }),\n };\n});\n\nvi.mock('@clack/prompts', () => ({\n default: {\n log: {\n error: mocks.clackError,\n },\n },\n}));\n\nvi.mock('@sentry/node', () => ({\n setTag: mocks.setTag,\n}));\n\nvi.mock('../../src/apple/search-xcode-project-at-path', () => ({\n searchXcodeProjectAtPath: mocks.searchXcodeProjectAtPath,\n}));\n\nvi.mock('../../src/apple/xcode-manager', () => ({\n XcodeProject: mocks.XcodeProject,\n}));\n\nvi.mock('../../src/telemetry', () => ({\n traceStep: mocks.traceStep,\n}));\n\nvi.mock('../../src/utils/clack', () => ({\n abort: mocks.abort,\n askForItemSelection: mocks.askForItemSelection,\n}));\n\nvi.mock('../../src/utils/debug', () => ({\n debug: mocks.debug,\n}));\n\nimport {\n lookupXcodeProject,\n selectXcodeTarget,\n} from '../../src/apple/lookup-xcode-project';\n\nfunction createProject(projectDir: string, projectName: string): string {\n const projectPath = path.join(projectDir, projectName);\n fs.mkdirSync(projectPath, { recursive: true });\n const pbxprojPath = path.join(projectPath, 'project.pbxproj');\n fs.writeFileSync(pbxprojPath, 'mock pbxproj');\n\n return pbxprojPath;\n}\n\nfunction createMockXcodeProject(\n pbxprojPath: string,\n): Parameters<typeof selectXcodeTarget>[0] {\n const XcodeProjectConstructor = mocks.XcodeProject as unknown as {\n new (projectPath: string): MockXcodeProject;\n };\n\n return new XcodeProjectConstructor(pbxprojPath) as unknown as Parameters<\n typeof selectXcodeTarget\n >[0];\n}\n\ndescribe('lookup-xcode-project', () => {\n let projectDir: string;\n\n beforeEach(() => {\n projectDir = fs.mkdtempSync(\n path.join(os.tmpdir(), 'lookup-xcode-project-'),\n );\n vi.clearAllMocks();\n mocks.targetsByProjectPath.clear();\n });\n\n afterEach(() => {\n fs.rmSync(projectDir, { force: true, recursive: true });\n });\n\n describe('lookupXcodeProject', () => {\n it('returns an Xcode project without selecting a target', async () => {\n const pbxprojPath = createProject(projectDir, 'App.xcodeproj');\n mocks.searchXcodeProjectAtPath.mockReturnValue(['App.xcodeproj']);\n mocks.targetsByProjectPath.set(pbxprojPath, ['App']);\n\n const result = await lookupXcodeProject({ projectDir });\n\n expect(mocks.searchXcodeProjectAtPath).toHaveBeenCalledWith(projectDir);\n expect(mocks.XcodeProject).toHaveBeenCalledWith(pbxprojPath);\n expect(result).toEqual(\n expect.objectContaining({ projectPath: pbxprojPath }),\n );\n expect(mocks.askForItemSelection).not.toHaveBeenCalledWith(\n ['App'],\n 'Which target do you want to add Sentry to?',\n );\n });\n\n it('prompts when multiple Xcode projects are found', async () => {\n createProject(projectDir, 'First.xcodeproj');\n const selectedPbxprojPath = createProject(projectDir, 'Second.xcodeproj');\n mocks.searchXcodeProjectAtPath.mockReturnValue([\n 'First.xcodeproj',\n 'Second.xcodeproj',\n ]);\n mocks.askForItemSelection.mockResolvedValue({\n value: 'Second.xcodeproj',\n });\n\n const result = await lookupXcodeProject({ projectDir });\n\n expect(mocks.askForItemSelection).toHaveBeenCalledWith(\n ['First.xcodeproj', 'Second.xcodeproj'],\n 'Which project do you want to add Sentry to?',\n );\n expect(result).toEqual(\n expect.objectContaining({ projectPath: selectedPbxprojPath }),\n );\n });\n\n it('fails instead of prompting when multiple Xcode projects are found in non-interactive mode', async () => {\n createProject(projectDir, 'First.xcodeproj');\n createProject(projectDir, 'Second.xcodeproj');\n mocks.searchXcodeProjectAtPath.mockReturnValue([\n 'First.xcodeproj',\n 'Second.xcodeproj',\n ]);\n\n await expect(\n lookupXcodeProject({ projectDir, nonInteractive: true }),\n ).rejects.toThrow('abort');\n\n expect(mocks.askForItemSelection).not.toHaveBeenCalled();\n expect(mocks.clackError).toHaveBeenCalledWith(\n expect.stringContaining('Multiple Xcode projects found'),\n );\n });\n });\n\n describe('selectXcodeTarget', () => {\n it('returns the only target without prompting', async () => {\n const pbxprojPath = createProject(projectDir, 'App.xcodeproj');\n mocks.targetsByProjectPath.set(pbxprojPath, ['App']);\n const xcProject = createMockXcodeProject(pbxprojPath);\n\n const result = await selectXcodeTarget(xcProject);\n\n expect(result).toBe('App');\n expect(mocks.askForItemSelection).not.toHaveBeenCalled();\n });\n\n it('prompts when multiple targets are available', async () => {\n const pbxprojPath = createProject(projectDir, 'App.xcodeproj');\n mocks.targetsByProjectPath.set(pbxprojPath, ['App', 'Widget']);\n mocks.askForItemSelection.mockResolvedValue({ value: 'Widget' });\n const xcProject = createMockXcodeProject(pbxprojPath);\n\n const result = await selectXcodeTarget(xcProject);\n\n expect(mocks.askForItemSelection).toHaveBeenCalledWith(\n ['App', 'Widget'],\n 'Which target do you want to add Sentry to?',\n );\n expect(result).toBe('Widget');\n });\n\n it('selects from custom target candidates', async () => {\n const pbxprojPath = createProject(projectDir, 'App.xcodeproj');\n mocks.targetsByProjectPath.set(pbxprojPath, ['App']);\n mocks.askForItemSelection.mockResolvedValue({ value: 'AppUITests' });\n const xcProject = createMockXcodeProject(pbxprojPath);\n\n const result = await selectXcodeTarget(xcProject, {\n targetNames: ['AppTests', 'AppUITests'],\n promptMessage: 'Which test target should render SnapshotPreviews?',\n });\n\n expect(mocks.askForItemSelection).toHaveBeenCalledWith(\n ['AppTests', 'AppUITests'],\n 'Which test target should render SnapshotPreviews?',\n );\n expect(result).toBe('AppUITests');\n });\n });\n});\n"]}