@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,186 @@
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 path = __importStar(require("node:path"));
28
+ const vitest_1 = require("vitest");
29
+ const configure_snapshotpreviews_xcode_project_1 = require("../../../src/apple/snapshots/configure-snapshotpreviews-xcode-project");
30
+ const snapshot_test_file_1 = require("../../../src/apple/snapshots/snapshot-test-file");
31
+ const snapshotpreviews_package_1 = require("../../../src/apple/snapshots/snapshotpreviews-package");
32
+ const xcode_manager_1 = require("../../../src/apple/xcode-manager");
33
+ const hosted_test_target_fixture_1 = require("./hosted-test-target-fixture");
34
+ vitest_1.vi.mock('@clack/prompts', () => ({
35
+ log: {
36
+ info: vitest_1.vi.fn(),
37
+ success: vitest_1.vi.fn(),
38
+ step: vitest_1.vi.fn(),
39
+ },
40
+ }));
41
+ const projectObjectId = 'D4E604C52D50CEEC00CAB00F';
42
+ const productsGroupId = 'D4E604CE2D50CEEC00CAB00F';
43
+ const hostedTestTargetIds = {
44
+ targetId: 'AAAABBBBCCCCDDDDEEEE0001',
45
+ frameworksBuildPhaseId: 'AAAABBBBCCCCDDDDEEEE0002',
46
+ sourcesBuildPhaseId: 'AAAABBBBCCCCDDDDEEEE0003',
47
+ debugBuildConfigurationId: 'AAAABBBBCCCCDDDDEEEE0004',
48
+ releaseBuildConfigurationId: 'AAAABBBBCCCCDDDDEEEE0005',
49
+ buildConfigurationListId: 'AAAABBBBCCCCDDDDEEEE0006',
50
+ productReferenceId: 'AAAABBBBCCCCDDDDEEEE0007',
51
+ };
52
+ function getTargetByName(xcodeProject, targetName) {
53
+ const target = Object.values(xcodeProject.objects.PBXNativeTarget ?? {}).find((candidate) => {
54
+ return typeof candidate !== 'string' && candidate.name === targetName;
55
+ });
56
+ if (!target) {
57
+ throw new Error(`Target not found: ${targetName}`);
58
+ }
59
+ return target;
60
+ }
61
+ function getProductDependencyIds(xcodeProject, productName) {
62
+ return Object.entries(xcodeProject.objects.XCSwiftPackageProductDependency ?? {}).reduce((ids, [id, productDependency]) => {
63
+ if (id.endsWith('_comment') ||
64
+ typeof productDependency === 'string' ||
65
+ productDependency.productName !== productName) {
66
+ return ids;
67
+ }
68
+ return ids.concat(id);
69
+ }, new Array());
70
+ }
71
+ function getProductDependency(xcodeProject, productDependencyId) {
72
+ const productDependency = xcodeProject.objects.XCSwiftPackageProductDependency?.[productDependencyId];
73
+ if (!productDependency || typeof productDependency === 'string') {
74
+ throw new Error(`Product dependency not found: ${productDependencyId}`);
75
+ }
76
+ return productDependency;
77
+ }
78
+ function getFrameworkProductRefs(xcodeProject, targetName) {
79
+ return (getTargetByName(xcodeProject, targetName).buildPhases ?? []).reduce((productRefs, buildPhaseReference) => {
80
+ const buildPhase = xcodeProject.objects.PBXFrameworksBuildPhase?.[buildPhaseReference.value];
81
+ if (!buildPhase || typeof buildPhase === 'string') {
82
+ return productRefs;
83
+ }
84
+ return productRefs.concat((buildPhase.files ?? []).flatMap((file) => {
85
+ const buildFile = xcodeProject.objects.PBXBuildFile?.[file.value];
86
+ return buildFile &&
87
+ typeof buildFile !== 'string' &&
88
+ typeof buildFile.productRef === 'string'
89
+ ? [buildFile.productRef]
90
+ : [];
91
+ }));
92
+ }, new Array());
93
+ }
94
+ function getSnapshotPreviewsPackageReferenceIds(xcodeProject) {
95
+ return Object.entries(xcodeProject.objects.XCRemoteSwiftPackageReference ?? {}).reduce((ids, [id, packageReference]) => {
96
+ if (id.endsWith('_comment') ||
97
+ typeof packageReference === 'string' ||
98
+ packageReference.repositoryURL !== `"${snapshotpreviews_package_1.SNAPSHOTPREVIEWS_PACKAGE_URL}"`) {
99
+ return ids;
100
+ }
101
+ return ids.concat(id);
102
+ }, new Array());
103
+ }
104
+ (0, vitest_1.describe)('SnapshotPreviews hosted XCTest Xcode project smoke coverage', () => {
105
+ (0, vitest_1.it)('mutates, reparses, and reruns without duplicating package or source membership', () => {
106
+ const pbxprojPath = (0, hosted_test_target_fixture_1.copySingleTargetProjectToTemp)('snapshotpreviews-xcode-smoke-');
107
+ const xcodeProject = new xcode_manager_1.XcodeProject(pbxprojPath);
108
+ (0, hosted_test_target_fixture_1.addHostedUnitTestTarget)(xcodeProject, {
109
+ ids: hostedTestTargetIds,
110
+ includeSourcesBuildPhase: true,
111
+ projectObjectId,
112
+ productsGroupId,
113
+ });
114
+ const snapshotTestResult = (0, snapshot_test_file_1.ensureSnapshotTestFile)({
115
+ xcodeProject,
116
+ hostedTestTargetName: 'ProjectTests',
117
+ });
118
+ const packageResult = (0, configure_snapshotpreviews_xcode_project_1.configureSnapshotPreviewsXcodeProject)({
119
+ xcodeProject,
120
+ hostedTestTargetName: 'ProjectTests',
121
+ previewTargetNames: ['Project'],
122
+ });
123
+ xcodeProject.write();
124
+ (0, vitest_1.expect)(snapshotTestResult.changed).toBe(true);
125
+ (0, vitest_1.expect)(snapshotTestResult.included).toBe(true);
126
+ if (!snapshotTestResult.included) {
127
+ throw new Error('Expected snapshot test file to be included');
128
+ }
129
+ (0, vitest_1.expect)(snapshotTestResult.filePath).toBe(path.join(xcodeProject.baseDir, 'ProjectTests', 'ProjectTestsSnapshotTest.swift'));
130
+ (0, vitest_1.expect)(packageResult).toEqual({
131
+ changed: true,
132
+ failedSnapshotPreferencesTargetNames: [],
133
+ linked: true,
134
+ });
135
+ const firstSerializedProject = fs.readFileSync(pbxprojPath, 'utf8');
136
+ const reparsedProject = new xcode_manager_1.XcodeProject(pbxprojPath);
137
+ (0, vitest_1.expect)(reparsedProject.getUnitTestTargetNames()).toContain('ProjectTests');
138
+ (0, vitest_1.expect)(getSnapshotPreviewsPackageReferenceIds(reparsedProject)).toHaveLength(1);
139
+ const snapshottingTestsProductDependencyIds = getProductDependencyIds(reparsedProject, snapshotpreviews_package_1.SNAPSHOTPREVIEWS_SNAPSHOT_TESTS_PRODUCT);
140
+ const snapshotPreferencesProductDependencyIds = getProductDependencyIds(reparsedProject, snapshotpreviews_package_1.SNAPSHOTPREVIEWS_PREFERENCES_PRODUCT);
141
+ (0, vitest_1.expect)(snapshottingTestsProductDependencyIds).toHaveLength(1);
142
+ (0, vitest_1.expect)(snapshotPreferencesProductDependencyIds).toHaveLength(1);
143
+ (0, vitest_1.expect)(getProductDependency(reparsedProject, snapshottingTestsProductDependencyIds[0]).package).toBe(getSnapshotPreviewsPackageReferenceIds(reparsedProject)[0]);
144
+ (0, vitest_1.expect)(getProductDependency(reparsedProject, snapshotPreferencesProductDependencyIds[0]).package).toBe(getSnapshotPreviewsPackageReferenceIds(reparsedProject)[0]);
145
+ (0, vitest_1.expect)(getFrameworkProductRefs(reparsedProject, 'ProjectTests')).toEqual([
146
+ snapshottingTestsProductDependencyIds[0],
147
+ ]);
148
+ (0, vitest_1.expect)(getFrameworkProductRefs(reparsedProject, 'Project')).toEqual([
149
+ snapshotPreferencesProductDependencyIds[0],
150
+ ]);
151
+ (0, vitest_1.expect)(getTargetByName(reparsedProject, 'ProjectTests')
152
+ .packageProductDependencies).toEqual([
153
+ {
154
+ value: snapshottingTestsProductDependencyIds[0],
155
+ comment: snapshotpreviews_package_1.SNAPSHOTPREVIEWS_SNAPSHOT_TESTS_PRODUCT,
156
+ },
157
+ ]);
158
+ (0, vitest_1.expect)(getTargetByName(reparsedProject, 'Project').packageProductDependencies).toEqual([
159
+ {
160
+ value: snapshotPreferencesProductDependencyIds[0],
161
+ comment: snapshotpreviews_package_1.SNAPSHOTPREVIEWS_PREFERENCES_PRODUCT,
162
+ },
163
+ ]);
164
+ (0, vitest_1.expect)(reparsedProject
165
+ .getSourceFilesForTarget('ProjectTests')
166
+ ?.filter((sourceFilePath) => sourceFilePath.endsWith('ProjectTests/ProjectTestsSnapshotTest.swift'))).toHaveLength(1);
167
+ const secondSnapshotTestResult = (0, snapshot_test_file_1.ensureSnapshotTestFile)({
168
+ xcodeProject: reparsedProject,
169
+ hostedTestTargetName: 'ProjectTests',
170
+ });
171
+ const secondPackageResult = (0, configure_snapshotpreviews_xcode_project_1.configureSnapshotPreviewsXcodeProject)({
172
+ xcodeProject: reparsedProject,
173
+ hostedTestTargetName: 'ProjectTests',
174
+ previewTargetNames: ['Project'],
175
+ });
176
+ reparsedProject.write();
177
+ (0, vitest_1.expect)(secondSnapshotTestResult.changed).toBe(false);
178
+ (0, vitest_1.expect)(secondPackageResult).toEqual({
179
+ changed: false,
180
+ failedSnapshotPreferencesTargetNames: [],
181
+ linked: true,
182
+ });
183
+ (0, vitest_1.expect)(fs.readFileSync(pbxprojPath, 'utf8')).toBe(firstSerializedProject);
184
+ }, 15000);
185
+ });
186
+ //# sourceMappingURL=snapshotpreviews-xcode-smoke.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshotpreviews-xcode-smoke.test.js","sourceRoot":"","sources":["../../../../test/apple/snapshots/snapshotpreviews-xcode-smoke.test.ts"],"names":[],"mappings":"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","sourcesContent":["import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { describe, expect, it, vi } from 'vitest';\nimport type { PBXNativeTarget } from 'xcode';\n\nimport { configureSnapshotPreviewsXcodeProject } from '../../../src/apple/snapshots/configure-snapshotpreviews-xcode-project';\nimport { ensureSnapshotTestFile } from '../../../src/apple/snapshots/snapshot-test-file';\nimport {\n SNAPSHOTPREVIEWS_PACKAGE_URL,\n SNAPSHOTPREVIEWS_PREFERENCES_PRODUCT,\n SNAPSHOTPREVIEWS_SNAPSHOT_TESTS_PRODUCT,\n} from '../../../src/apple/snapshots/snapshotpreviews-package';\nimport { XcodeProject } from '../../../src/apple/xcode-manager';\nimport {\n addHostedUnitTestTarget,\n copySingleTargetProjectToTemp,\n} from './hosted-test-target-fixture';\n\nvi.mock('@clack/prompts', () => ({\n log: {\n info: vi.fn(),\n success: vi.fn(),\n step: vi.fn(),\n },\n}));\n\nconst projectObjectId = 'D4E604C52D50CEEC00CAB00F';\nconst productsGroupId = 'D4E604CE2D50CEEC00CAB00F';\n\nconst hostedTestTargetIds = {\n targetId: 'AAAABBBBCCCCDDDDEEEE0001',\n frameworksBuildPhaseId: 'AAAABBBBCCCCDDDDEEEE0002',\n sourcesBuildPhaseId: 'AAAABBBBCCCCDDDDEEEE0003',\n debugBuildConfigurationId: 'AAAABBBBCCCCDDDDEEEE0004',\n releaseBuildConfigurationId: 'AAAABBBBCCCCDDDDEEEE0005',\n buildConfigurationListId: 'AAAABBBBCCCCDDDDEEEE0006',\n productReferenceId: 'AAAABBBBCCCCDDDDEEEE0007',\n};\n\nfunction getTargetByName(\n xcodeProject: XcodeProject,\n targetName: string,\n): PBXNativeTarget {\n const target = Object.values(xcodeProject.objects.PBXNativeTarget ?? {}).find(\n (candidate) => {\n return typeof candidate !== 'string' && candidate.name === targetName;\n },\n ) as PBXNativeTarget | undefined;\n\n if (!target) {\n throw new Error(`Target not found: ${targetName}`);\n }\n\n return target;\n}\n\nfunction getProductDependencyIds(\n xcodeProject: XcodeProject,\n productName: string,\n): string[] {\n return Object.entries(\n xcodeProject.objects.XCSwiftPackageProductDependency ?? {},\n ).reduce((ids, [id, productDependency]) => {\n if (\n id.endsWith('_comment') ||\n typeof productDependency === 'string' ||\n productDependency.productName !== productName\n ) {\n return ids;\n }\n\n return ids.concat(id);\n }, new Array<string>());\n}\n\nfunction getProductDependency(\n xcodeProject: XcodeProject,\n productDependencyId: string,\n) {\n const productDependency =\n xcodeProject.objects.XCSwiftPackageProductDependency?.[productDependencyId];\n if (!productDependency || typeof productDependency === 'string') {\n throw new Error(`Product dependency not found: ${productDependencyId}`);\n }\n\n return productDependency;\n}\n\nfunction getFrameworkProductRefs(\n xcodeProject: XcodeProject,\n targetName: string,\n): string[] {\n return (getTargetByName(xcodeProject, targetName).buildPhases ?? []).reduce(\n (productRefs, buildPhaseReference) => {\n const buildPhase =\n xcodeProject.objects.PBXFrameworksBuildPhase?.[\n buildPhaseReference.value\n ];\n if (!buildPhase || typeof buildPhase === 'string') {\n return productRefs;\n }\n\n return productRefs.concat(\n (buildPhase.files ?? []).flatMap((file) => {\n const buildFile = xcodeProject.objects.PBXBuildFile?.[file.value];\n return buildFile &&\n typeof buildFile !== 'string' &&\n typeof buildFile.productRef === 'string'\n ? [buildFile.productRef]\n : [];\n }),\n );\n },\n new Array<string>(),\n );\n}\n\nfunction getSnapshotPreviewsPackageReferenceIds(\n xcodeProject: XcodeProject,\n): string[] {\n return Object.entries(\n xcodeProject.objects.XCRemoteSwiftPackageReference ?? {},\n ).reduce((ids, [id, packageReference]) => {\n if (\n id.endsWith('_comment') ||\n typeof packageReference === 'string' ||\n packageReference.repositoryURL !== `\"${SNAPSHOTPREVIEWS_PACKAGE_URL}\"`\n ) {\n return ids;\n }\n\n return ids.concat(id);\n }, new Array<string>());\n}\n\ndescribe('SnapshotPreviews hosted XCTest Xcode project smoke coverage', () => {\n it('mutates, reparses, and reruns without duplicating package or source membership', () => {\n const pbxprojPath = copySingleTargetProjectToTemp(\n 'snapshotpreviews-xcode-smoke-',\n );\n const xcodeProject = new XcodeProject(pbxprojPath);\n addHostedUnitTestTarget(xcodeProject, {\n ids: hostedTestTargetIds,\n includeSourcesBuildPhase: true,\n projectObjectId,\n productsGroupId,\n });\n\n const snapshotTestResult = ensureSnapshotTestFile({\n xcodeProject,\n hostedTestTargetName: 'ProjectTests',\n });\n const packageResult = configureSnapshotPreviewsXcodeProject({\n xcodeProject,\n hostedTestTargetName: 'ProjectTests',\n previewTargetNames: ['Project'],\n });\n xcodeProject.write();\n\n expect(snapshotTestResult.changed).toBe(true);\n expect(snapshotTestResult.included).toBe(true);\n if (!snapshotTestResult.included) {\n throw new Error('Expected snapshot test file to be included');\n }\n expect(snapshotTestResult.filePath).toBe(\n path.join(\n xcodeProject.baseDir,\n 'ProjectTests',\n 'ProjectTestsSnapshotTest.swift',\n ),\n );\n expect(packageResult).toEqual({\n changed: true,\n failedSnapshotPreferencesTargetNames: [],\n linked: true,\n });\n\n const firstSerializedProject = fs.readFileSync(pbxprojPath, 'utf8');\n const reparsedProject = new XcodeProject(pbxprojPath);\n\n expect(reparsedProject.getUnitTestTargetNames()).toContain('ProjectTests');\n expect(\n getSnapshotPreviewsPackageReferenceIds(reparsedProject),\n ).toHaveLength(1);\n\n const snapshottingTestsProductDependencyIds = getProductDependencyIds(\n reparsedProject,\n SNAPSHOTPREVIEWS_SNAPSHOT_TESTS_PRODUCT,\n );\n const snapshotPreferencesProductDependencyIds = getProductDependencyIds(\n reparsedProject,\n SNAPSHOTPREVIEWS_PREFERENCES_PRODUCT,\n );\n expect(snapshottingTestsProductDependencyIds).toHaveLength(1);\n expect(snapshotPreferencesProductDependencyIds).toHaveLength(1);\n expect(\n getProductDependency(\n reparsedProject,\n snapshottingTestsProductDependencyIds[0],\n ).package,\n ).toBe(getSnapshotPreviewsPackageReferenceIds(reparsedProject)[0]);\n expect(\n getProductDependency(\n reparsedProject,\n snapshotPreferencesProductDependencyIds[0],\n ).package,\n ).toBe(getSnapshotPreviewsPackageReferenceIds(reparsedProject)[0]);\n expect(getFrameworkProductRefs(reparsedProject, 'ProjectTests')).toEqual([\n snapshottingTestsProductDependencyIds[0],\n ]);\n expect(getFrameworkProductRefs(reparsedProject, 'Project')).toEqual([\n snapshotPreferencesProductDependencyIds[0],\n ]);\n\n expect(\n getTargetByName(reparsedProject, 'ProjectTests')\n .packageProductDependencies,\n ).toEqual([\n {\n value: snapshottingTestsProductDependencyIds[0],\n comment: SNAPSHOTPREVIEWS_SNAPSHOT_TESTS_PRODUCT,\n },\n ]);\n expect(\n getTargetByName(reparsedProject, 'Project').packageProductDependencies,\n ).toEqual([\n {\n value: snapshotPreferencesProductDependencyIds[0],\n comment: SNAPSHOTPREVIEWS_PREFERENCES_PRODUCT,\n },\n ]);\n expect(\n reparsedProject\n .getSourceFilesForTarget('ProjectTests')\n ?.filter((sourceFilePath) =>\n sourceFilePath.endsWith(\n 'ProjectTests/ProjectTestsSnapshotTest.swift',\n ),\n ),\n ).toHaveLength(1);\n\n const secondSnapshotTestResult = ensureSnapshotTestFile({\n xcodeProject: reparsedProject,\n hostedTestTargetName: 'ProjectTests',\n });\n const secondPackageResult = configureSnapshotPreviewsXcodeProject({\n xcodeProject: reparsedProject,\n hostedTestTargetName: 'ProjectTests',\n previewTargetNames: ['Project'],\n });\n reparsedProject.write();\n\n expect(secondSnapshotTestResult.changed).toBe(false);\n expect(secondPackageResult).toEqual({\n changed: false,\n failedSnapshotPreferencesTargetNames: [],\n linked: true,\n });\n expect(fs.readFileSync(pbxprojPath, 'utf8')).toBe(firstSerializedProject);\n }, 15_000);\n});\n"]}
@@ -0,0 +1,192 @@
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
+ askToInstallSentryCLI: vitest_1.vi.fn(),
32
+ executeSync: vitest_1.vi.fn(),
33
+ hasSentryCLI: vitest_1.vi.fn(),
34
+ info: vitest_1.vi.fn(),
35
+ installSentryCLI: vitest_1.vi.fn(),
36
+ setTag: vitest_1.vi.fn(),
37
+ success: vitest_1.vi.fn(),
38
+ warn: vitest_1.vi.fn(),
39
+ }));
40
+ vitest_1.vi.mock('@clack/prompts', () => ({
41
+ default: {
42
+ log: {
43
+ info: mocks.info,
44
+ success: mocks.success,
45
+ warn: mocks.warn,
46
+ },
47
+ },
48
+ }));
49
+ vitest_1.vi.mock('@sentry/node', () => ({
50
+ setTag: mocks.setTag,
51
+ }));
52
+ vitest_1.vi.mock('../../../src/telemetry', () => ({
53
+ traceStep: async (_name, callback) => await callback(),
54
+ }));
55
+ vitest_1.vi.mock('../../../src/utils/bash', () => ({
56
+ executeSync: mocks.executeSync,
57
+ hasSentryCLI: mocks.hasSentryCLI,
58
+ installSentryCLI: mocks.installSentryCLI,
59
+ }));
60
+ vitest_1.vi.mock('../../../src/utils/clack', () => ({
61
+ askToInstallSentryCLI: mocks.askToInstallSentryCLI,
62
+ }));
63
+ const snapshots_cli_preflight_1 = require("../../../src/apple/snapshots/snapshots-cli-preflight");
64
+ function getVerificationGuidance(projectDir) {
65
+ return {
66
+ appId: 'com.getsentry.App',
67
+ hostedTestTargetName: 'AppTests',
68
+ projectDir,
69
+ projectPath: path.join(projectDir, 'App.xcodeproj'),
70
+ schemeName: 'App',
71
+ snapshotTestClassName: 'AppTestsSnapshotTest',
72
+ };
73
+ }
74
+ (0, vitest_1.describe)('snapshots CLI preflight', () => {
75
+ (0, vitest_1.beforeEach)(() => {
76
+ vitest_1.vi.clearAllMocks();
77
+ });
78
+ (0, vitest_1.it)('offers to install sentry-cli with snapshots-aware warning when missing', async () => {
79
+ mocks.hasSentryCLI.mockReturnValue(false);
80
+ mocks.askToInstallSentryCLI.mockResolvedValue(false);
81
+ const projectDir = fs.mkdtempSync(path.join(os.tmpdir(), 'snapshot-cli-missing-'));
82
+ await (0, snapshots_cli_preflight_1.checkInstalledCLISnapshots)({
83
+ projectDir,
84
+ nonInteractive: false,
85
+ verificationGuidance: getVerificationGuidance(projectDir),
86
+ });
87
+ (0, vitest_1.expect)(mocks.askToInstallSentryCLI).toHaveBeenCalledTimes(1);
88
+ (0, vitest_1.expect)(mocks.warn).toHaveBeenCalledWith(vitest_1.expect.stringContaining('upload snapshots to Sentry'));
89
+ (0, vitest_1.expect)(mocks.executeSync).not.toHaveBeenCalled();
90
+ });
91
+ (0, vitest_1.it)('does not prompt to install sentry-cli in non-interactive mode', async () => {
92
+ mocks.hasSentryCLI.mockReturnValue(false);
93
+ const projectDir = fs.mkdtempSync(path.join(os.tmpdir(), 'snapshot-cli-non-interactive-'));
94
+ await (0, snapshots_cli_preflight_1.checkInstalledCLISnapshots)({
95
+ projectDir,
96
+ nonInteractive: true,
97
+ verificationGuidance: getVerificationGuidance(projectDir),
98
+ });
99
+ (0, vitest_1.expect)(mocks.askToInstallSentryCLI).not.toHaveBeenCalled();
100
+ (0, vitest_1.expect)(mocks.warn).toHaveBeenCalledWith(vitest_1.expect.stringContaining('upload snapshots to Sentry'));
101
+ (0, vitest_1.expect)(mocks.info).toHaveBeenCalledWith(vitest_1.expect.stringContaining('sentry-cli snapshots upload'));
102
+ (0, vitest_1.expect)(mocks.executeSync).not.toHaveBeenCalled();
103
+ });
104
+ (0, vitest_1.it)('verifies snapshots upload support and prefers existing Fastlane guidance', async () => {
105
+ const projectDir = fs.mkdtempSync(path.join(os.tmpdir(), 'snapshot-cli-'));
106
+ const fastlaneDir = path.join(projectDir, 'fastlane');
107
+ fs.mkdirSync(fastlaneDir);
108
+ fs.writeFileSync(path.join(fastlaneDir, 'Fastfile'), 'platform :ios do\n lane :upload_sentry_snapshots do |options|\n sentry_upload_snapshots(path: options[:path])\n end\nend\n');
109
+ mocks.hasSentryCLI.mockReturnValue(true);
110
+ await (0, snapshots_cli_preflight_1.checkInstalledCLISnapshots)({
111
+ projectDir,
112
+ nonInteractive: false,
113
+ verificationGuidance: getVerificationGuidance(projectDir),
114
+ });
115
+ (0, vitest_1.expect)(mocks.executeSync).toHaveBeenCalledWith('sentry-cli snapshots upload --help');
116
+ (0, vitest_1.expect)(mocks.success).toHaveBeenCalledWith('sentry-cli snapshots upload is available.');
117
+ (0, vitest_1.expect)(mocks.info).toHaveBeenCalledWith(vitest_1.expect.stringContaining('xcodebuild test'));
118
+ (0, vitest_1.expect)(mocks.info).toHaveBeenCalledWith(vitest_1.expect.stringContaining('-project App.xcodeproj'));
119
+ (0, vitest_1.expect)(mocks.info).toHaveBeenCalledWith(vitest_1.expect.stringContaining('-scheme App'));
120
+ (0, vitest_1.expect)(mocks.info).toHaveBeenCalledWith(vitest_1.expect.stringContaining('-only-testing:AppTests/AppTestsSnapshotTest'));
121
+ (0, vitest_1.expect)(mocks.info).toHaveBeenCalledWith(vitest_1.expect.stringContaining('bundle exec fastlane ios upload_sentry_snapshots'));
122
+ });
123
+ (0, vitest_1.it)('prints xcodebuild export and sentry-cli upload guidance', async () => {
124
+ const projectDir = fs.mkdtempSync(path.join(os.tmpdir(), 'snapshot-cli-'));
125
+ mocks.hasSentryCLI.mockReturnValue(true);
126
+ await (0, snapshots_cli_preflight_1.checkInstalledCLISnapshots)({
127
+ projectDir,
128
+ nonInteractive: false,
129
+ verificationGuidance: getVerificationGuidance(projectDir),
130
+ });
131
+ (0, vitest_1.expect)(mocks.info).toHaveBeenCalledWith(vitest_1.expect.stringContaining('TEST_RUNNER_SNAPSHOTS_EXPORT_DIR'));
132
+ (0, vitest_1.expect)(mocks.info).toHaveBeenCalledWith(vitest_1.expect.stringContaining('-only-testing:AppTests/AppTestsSnapshotTest'));
133
+ (0, vitest_1.expect)(mocks.info).toHaveBeenCalledWith(vitest_1.expect.stringContaining('sentry-cli snapshots upload'));
134
+ (0, vitest_1.expect)(mocks.info).toHaveBeenCalledWith(vitest_1.expect.stringContaining('--app-id com.getsentry.App'));
135
+ });
136
+ (0, vitest_1.it)('uses the provided snapshot test class name in xcodebuild guidance', async () => {
137
+ const projectDir = fs.mkdtempSync(path.join(os.tmpdir(), 'snapshot-cli-'));
138
+ mocks.hasSentryCLI.mockReturnValue(true);
139
+ await (0, snapshots_cli_preflight_1.checkInstalledCLISnapshots)({
140
+ projectDir,
141
+ nonInteractive: false,
142
+ verificationGuidance: {
143
+ ...getVerificationGuidance(projectDir),
144
+ snapshotTestClassName: 'CustomSnapshots',
145
+ },
146
+ });
147
+ (0, vitest_1.expect)(mocks.info).toHaveBeenCalledWith(vitest_1.expect.stringContaining('-only-testing:AppTests/CustomSnapshots'));
148
+ (0, vitest_1.expect)(mocks.info).not.toHaveBeenCalledWith(vitest_1.expect.stringContaining('-only-testing:AppTests/AppTestsSnapshotTest'));
149
+ });
150
+ (0, vitest_1.it)('uses a scheme placeholder when no verification scheme was detected', async () => {
151
+ const projectDir = fs.mkdtempSync(path.join(os.tmpdir(), 'snapshot-cli-'));
152
+ mocks.hasSentryCLI.mockReturnValue(true);
153
+ await (0, snapshots_cli_preflight_1.checkInstalledCLISnapshots)({
154
+ projectDir,
155
+ nonInteractive: false,
156
+ verificationGuidance: {
157
+ ...getVerificationGuidance(projectDir),
158
+ schemeName: undefined,
159
+ },
160
+ });
161
+ (0, vitest_1.expect)(mocks.info).toHaveBeenCalledWith(vitest_1.expect.stringContaining('-scheme <scheme>'));
162
+ (0, vitest_1.expect)(mocks.info).not.toHaveBeenCalledWith(vitest_1.expect.stringContaining("-scheme '<scheme>'"));
163
+ });
164
+ (0, vitest_1.it)('uses an explicit app id placeholder when the bundle identifier is unavailable', async () => {
165
+ const projectDir = fs.mkdtempSync(path.join(os.tmpdir(), 'snapshot-cli-'));
166
+ const verificationGuidance = {
167
+ ...getVerificationGuidance(projectDir),
168
+ appId: undefined,
169
+ };
170
+ mocks.hasSentryCLI.mockReturnValue(true);
171
+ await (0, snapshots_cli_preflight_1.checkInstalledCLISnapshots)({
172
+ projectDir,
173
+ nonInteractive: false,
174
+ verificationGuidance,
175
+ });
176
+ (0, vitest_1.expect)(mocks.info).toHaveBeenCalledWith(vitest_1.expect.stringContaining('--app-id YOUR_APP_BUNDLE_ID'));
177
+ (0, vitest_1.expect)(mocks.info).not.toHaveBeenCalledWith(vitest_1.expect.stringContaining('com.example.MyApp'));
178
+ (0, vitest_1.expect)(mocks.info).not.toHaveBeenCalledWith(vitest_1.expect.stringContaining('<your-app-bundle-id>'));
179
+ });
180
+ (0, vitest_1.it)('detects existing Fastlane snapshots upload support', () => {
181
+ const projectDir = fs.mkdtempSync(path.join(os.tmpdir(), 'snapshot-fastlane-'));
182
+ const fastlaneDir = path.join(projectDir, 'fastlane');
183
+ fs.mkdirSync(fastlaneDir);
184
+ fs.writeFileSync(path.join(fastlaneDir, 'Fastfile'), 'lane :upload_sentry_snapshots do\n sentry_upload_snapshots(path: "snapshot-images")\nend\n');
185
+ (0, vitest_1.expect)((0, snapshots_cli_preflight_1.getSnapshotFastlaneGuidance)(projectDir)).toEqual({
186
+ fastfilePath: path.join(fastlaneDir, 'Fastfile'),
187
+ hasUploadLane: true,
188
+ hasSentryUploadAction: true,
189
+ });
190
+ });
191
+ });
192
+ //# sourceMappingURL=snapshots-cli-preflight.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshots-cli-preflight.test.js","sourceRoot":"","sources":["../../../../test/apple/snapshots/snapshots-cli-preflight.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 { beforeEach, describe, expect, it, vi } from 'vitest';\n\nconst mocks = vi.hoisted(() => ({\n askToInstallSentryCLI: vi.fn(),\n executeSync: vi.fn(),\n hasSentryCLI: vi.fn(),\n info: vi.fn(),\n installSentryCLI: vi.fn(),\n setTag: vi.fn(),\n success: vi.fn(),\n warn: vi.fn(),\n}));\n\nvi.mock('@clack/prompts', () => ({\n default: {\n log: {\n info: mocks.info,\n success: mocks.success,\n warn: mocks.warn,\n },\n },\n}));\n\nvi.mock('@sentry/node', () => ({\n setTag: mocks.setTag,\n}));\n\nvi.mock('../../../src/telemetry', () => ({\n traceStep: async (_name: string, callback: () => Promise<boolean>) =>\n await callback(),\n}));\n\nvi.mock('../../../src/utils/bash', () => ({\n executeSync: mocks.executeSync,\n hasSentryCLI: mocks.hasSentryCLI,\n installSentryCLI: mocks.installSentryCLI,\n}));\n\nvi.mock('../../../src/utils/clack', () => ({\n askToInstallSentryCLI: mocks.askToInstallSentryCLI,\n}));\n\nimport {\n checkInstalledCLISnapshots,\n getSnapshotFastlaneGuidance,\n} from '../../../src/apple/snapshots/snapshots-cli-preflight';\n\nfunction getVerificationGuidance(projectDir: string) {\n return {\n appId: 'com.getsentry.App',\n hostedTestTargetName: 'AppTests',\n projectDir,\n projectPath: path.join(projectDir, 'App.xcodeproj'),\n schemeName: 'App',\n snapshotTestClassName: 'AppTestsSnapshotTest',\n };\n}\n\ndescribe('snapshots CLI preflight', () => {\n beforeEach(() => {\n vi.clearAllMocks();\n });\n\n it('offers to install sentry-cli with snapshots-aware warning when missing', async () => {\n mocks.hasSentryCLI.mockReturnValue(false);\n mocks.askToInstallSentryCLI.mockResolvedValue(false);\n\n const projectDir = fs.mkdtempSync(\n path.join(os.tmpdir(), 'snapshot-cli-missing-'),\n );\n\n await checkInstalledCLISnapshots({\n projectDir,\n nonInteractive: false,\n verificationGuidance: getVerificationGuidance(projectDir),\n });\n\n expect(mocks.askToInstallSentryCLI).toHaveBeenCalledTimes(1);\n expect(mocks.warn).toHaveBeenCalledWith(\n expect.stringContaining('upload snapshots to Sentry'),\n );\n expect(mocks.executeSync).not.toHaveBeenCalled();\n });\n\n it('does not prompt to install sentry-cli in non-interactive mode', async () => {\n mocks.hasSentryCLI.mockReturnValue(false);\n\n const projectDir = fs.mkdtempSync(\n path.join(os.tmpdir(), 'snapshot-cli-non-interactive-'),\n );\n\n await checkInstalledCLISnapshots({\n projectDir,\n nonInteractive: true,\n verificationGuidance: getVerificationGuidance(projectDir),\n });\n\n expect(mocks.askToInstallSentryCLI).not.toHaveBeenCalled();\n expect(mocks.warn).toHaveBeenCalledWith(\n expect.stringContaining('upload snapshots to Sentry'),\n );\n expect(mocks.info).toHaveBeenCalledWith(\n expect.stringContaining('sentry-cli snapshots upload'),\n );\n expect(mocks.executeSync).not.toHaveBeenCalled();\n });\n\n it('verifies snapshots upload support and prefers existing Fastlane guidance', async () => {\n const projectDir = fs.mkdtempSync(path.join(os.tmpdir(), 'snapshot-cli-'));\n const fastlaneDir = path.join(projectDir, 'fastlane');\n fs.mkdirSync(fastlaneDir);\n fs.writeFileSync(\n path.join(fastlaneDir, 'Fastfile'),\n 'platform :ios do\\n lane :upload_sentry_snapshots do |options|\\n sentry_upload_snapshots(path: options[:path])\\n end\\nend\\n',\n );\n mocks.hasSentryCLI.mockReturnValue(true);\n\n await checkInstalledCLISnapshots({\n projectDir,\n nonInteractive: false,\n verificationGuidance: getVerificationGuidance(projectDir),\n });\n\n expect(mocks.executeSync).toHaveBeenCalledWith(\n 'sentry-cli snapshots upload --help',\n );\n expect(mocks.success).toHaveBeenCalledWith(\n 'sentry-cli snapshots upload is available.',\n );\n expect(mocks.info).toHaveBeenCalledWith(\n expect.stringContaining('xcodebuild test'),\n );\n expect(mocks.info).toHaveBeenCalledWith(\n expect.stringContaining('-project App.xcodeproj'),\n );\n expect(mocks.info).toHaveBeenCalledWith(\n expect.stringContaining('-scheme App'),\n );\n expect(mocks.info).toHaveBeenCalledWith(\n expect.stringContaining('-only-testing:AppTests/AppTestsSnapshotTest'),\n );\n expect(mocks.info).toHaveBeenCalledWith(\n expect.stringContaining(\n 'bundle exec fastlane ios upload_sentry_snapshots',\n ),\n );\n });\n\n it('prints xcodebuild export and sentry-cli upload guidance', async () => {\n const projectDir = fs.mkdtempSync(path.join(os.tmpdir(), 'snapshot-cli-'));\n mocks.hasSentryCLI.mockReturnValue(true);\n\n await checkInstalledCLISnapshots({\n projectDir,\n nonInteractive: false,\n verificationGuidance: getVerificationGuidance(projectDir),\n });\n\n expect(mocks.info).toHaveBeenCalledWith(\n expect.stringContaining('TEST_RUNNER_SNAPSHOTS_EXPORT_DIR'),\n );\n expect(mocks.info).toHaveBeenCalledWith(\n expect.stringContaining('-only-testing:AppTests/AppTestsSnapshotTest'),\n );\n expect(mocks.info).toHaveBeenCalledWith(\n expect.stringContaining('sentry-cli snapshots upload'),\n );\n expect(mocks.info).toHaveBeenCalledWith(\n expect.stringContaining('--app-id com.getsentry.App'),\n );\n });\n\n it('uses the provided snapshot test class name in xcodebuild guidance', async () => {\n const projectDir = fs.mkdtempSync(path.join(os.tmpdir(), 'snapshot-cli-'));\n mocks.hasSentryCLI.mockReturnValue(true);\n\n await checkInstalledCLISnapshots({\n projectDir,\n nonInteractive: false,\n verificationGuidance: {\n ...getVerificationGuidance(projectDir),\n snapshotTestClassName: 'CustomSnapshots',\n },\n });\n\n expect(mocks.info).toHaveBeenCalledWith(\n expect.stringContaining('-only-testing:AppTests/CustomSnapshots'),\n );\n expect(mocks.info).not.toHaveBeenCalledWith(\n expect.stringContaining('-only-testing:AppTests/AppTestsSnapshotTest'),\n );\n });\n\n it('uses a scheme placeholder when no verification scheme was detected', async () => {\n const projectDir = fs.mkdtempSync(path.join(os.tmpdir(), 'snapshot-cli-'));\n mocks.hasSentryCLI.mockReturnValue(true);\n\n await checkInstalledCLISnapshots({\n projectDir,\n nonInteractive: false,\n verificationGuidance: {\n ...getVerificationGuidance(projectDir),\n schemeName: undefined,\n },\n });\n\n expect(mocks.info).toHaveBeenCalledWith(\n expect.stringContaining('-scheme <scheme>'),\n );\n expect(mocks.info).not.toHaveBeenCalledWith(\n expect.stringContaining(\"-scheme '<scheme>'\"),\n );\n });\n\n it('uses an explicit app id placeholder when the bundle identifier is unavailable', async () => {\n const projectDir = fs.mkdtempSync(path.join(os.tmpdir(), 'snapshot-cli-'));\n const verificationGuidance = {\n ...getVerificationGuidance(projectDir),\n appId: undefined,\n };\n mocks.hasSentryCLI.mockReturnValue(true);\n\n await checkInstalledCLISnapshots({\n projectDir,\n nonInteractive: false,\n verificationGuidance,\n });\n\n expect(mocks.info).toHaveBeenCalledWith(\n expect.stringContaining('--app-id YOUR_APP_BUNDLE_ID'),\n );\n expect(mocks.info).not.toHaveBeenCalledWith(\n expect.stringContaining('com.example.MyApp'),\n );\n expect(mocks.info).not.toHaveBeenCalledWith(\n expect.stringContaining('<your-app-bundle-id>'),\n );\n });\n\n it('detects existing Fastlane snapshots upload support', () => {\n const projectDir = fs.mkdtempSync(\n path.join(os.tmpdir(), 'snapshot-fastlane-'),\n );\n const fastlaneDir = path.join(projectDir, 'fastlane');\n fs.mkdirSync(fastlaneDir);\n fs.writeFileSync(\n path.join(fastlaneDir, 'Fastfile'),\n 'lane :upload_sentry_snapshots do\\n sentry_upload_snapshots(path: \"snapshot-images\")\\nend\\n',\n );\n\n expect(getSnapshotFastlaneGuidance(projectDir)).toEqual({\n fastfilePath: path.join(fastlaneDir, 'Fastfile'),\n hasUploadLane: true,\n hasSentryUploadAction: true,\n });\n });\n});\n"]}
@@ -0,0 +1,77 @@
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 path = __importStar(require("node:path"));
28
+ const vitest_1 = require("vitest");
29
+ const xcode_manager_1 = require("../../../src/apple/xcode-manager");
30
+ const hosted_test_target_fixture_1 = require("./hosted-test-target-fixture");
31
+ vitest_1.vi.mock('@clack/prompts', () => ({
32
+ log: {
33
+ info: vitest_1.vi.fn(),
34
+ success: vitest_1.vi.fn(),
35
+ step: vitest_1.vi.fn(),
36
+ },
37
+ }));
38
+ function sourceBuildPhaseFiles(xcodeProject) {
39
+ const phase = xcodeProject.objects.PBXSourcesBuildPhase?.['D4E604C92D50CEEC00CAB00F'];
40
+ return phase?.files ?? [];
41
+ }
42
+ (0, vitest_1.describe)('XcodeProject Swift source-file insertion', () => {
43
+ (0, vitest_1.beforeEach)(() => {
44
+ vitest_1.vi.clearAllMocks();
45
+ });
46
+ (0, vitest_1.it)('adds a Swift source file to a classic PBXSourcesBuildPhase once', () => {
47
+ const xcodeProject = new xcode_manager_1.XcodeProject((0, hosted_test_target_fixture_1.copySingleTargetProjectToTemp)('snapshot-source-file-'));
48
+ const filePath = path.join(xcodeProject.baseDir, 'ProjectTests', 'SnapshotTest.swift');
49
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
50
+ fs.writeFileSync(filePath, 'import SnapshottingTests\n', 'utf8');
51
+ const firstResult = xcodeProject.addSwiftSourceFileToTarget({
52
+ targetName: 'Project',
53
+ filePath,
54
+ });
55
+ const secondResult = xcodeProject.addSwiftSourceFileToTarget({
56
+ targetName: 'Project',
57
+ filePath,
58
+ });
59
+ (0, vitest_1.expect)(firstResult).toEqual({ changed: true, included: true });
60
+ (0, vitest_1.expect)(secondResult).toEqual({ changed: false, included: true });
61
+ (0, vitest_1.expect)(sourceBuildPhaseFiles(xcodeProject)).toHaveLength(1);
62
+ (0, vitest_1.expect)(Object.values(xcodeProject.objects.PBXFileReference ?? {}).filter((fileReference) => typeof fileReference === 'object' &&
63
+ fileReference.path === 'ProjectTests/SnapshotTest.swift')).toHaveLength(1);
64
+ });
65
+ (0, vitest_1.it)('uses synchronized root group inclusion when the file is inside a target synchronized folder', () => {
66
+ const xcodeProject = new xcode_manager_1.XcodeProject((0, hosted_test_target_fixture_1.copySingleTargetProjectToTemp)('snapshot-source-file-'));
67
+ const filePath = path.join(xcodeProject.baseDir, 'Sources', 'SnapshotTest.swift');
68
+ fs.writeFileSync(filePath, 'import SnapshottingTests\n', 'utf8');
69
+ const result = xcodeProject.addSwiftSourceFileToTarget({
70
+ targetName: 'Project',
71
+ filePath,
72
+ });
73
+ (0, vitest_1.expect)(result).toEqual({ changed: false, included: true });
74
+ (0, vitest_1.expect)(sourceBuildPhaseFiles(xcodeProject)).toEqual([]);
75
+ });
76
+ });
77
+ //# sourceMappingURL=source-file-insertion.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source-file-insertion.test.js","sourceRoot":"","sources":["../../../../test/apple/snapshots/source-file-insertion.test.ts"],"names":[],"mappings":"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","sourcesContent":["import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { beforeEach, describe, expect, it, vi } from 'vitest';\nimport type { PBXSourcesBuildPhase } from 'xcode';\n\nimport { XcodeProject } from '../../../src/apple/xcode-manager';\nimport { copySingleTargetProjectToTemp } from './hosted-test-target-fixture';\n\nvi.mock('@clack/prompts', () => ({\n log: {\n info: vi.fn(),\n success: vi.fn(),\n step: vi.fn(),\n },\n}));\n\nfunction sourceBuildPhaseFiles(xcodeProject: XcodeProject): unknown[] {\n const phase = xcodeProject.objects.PBXSourcesBuildPhase?.[\n 'D4E604C92D50CEEC00CAB00F'\n ] as PBXSourcesBuildPhase | undefined;\n return phase?.files ?? [];\n}\n\ndescribe('XcodeProject Swift source-file insertion', () => {\n beforeEach(() => {\n vi.clearAllMocks();\n });\n\n it('adds a Swift source file to a classic PBXSourcesBuildPhase once', () => {\n const xcodeProject = new XcodeProject(\n copySingleTargetProjectToTemp('snapshot-source-file-'),\n );\n const filePath = path.join(\n xcodeProject.baseDir,\n 'ProjectTests',\n 'SnapshotTest.swift',\n );\n fs.mkdirSync(path.dirname(filePath), { recursive: true });\n fs.writeFileSync(filePath, 'import SnapshottingTests\\n', 'utf8');\n\n const firstResult = xcodeProject.addSwiftSourceFileToTarget({\n targetName: 'Project',\n filePath,\n });\n const secondResult = xcodeProject.addSwiftSourceFileToTarget({\n targetName: 'Project',\n filePath,\n });\n\n expect(firstResult).toEqual({ changed: true, included: true });\n expect(secondResult).toEqual({ changed: false, included: true });\n expect(sourceBuildPhaseFiles(xcodeProject)).toHaveLength(1);\n expect(\n Object.values(xcodeProject.objects.PBXFileReference ?? {}).filter(\n (fileReference) =>\n typeof fileReference === 'object' &&\n fileReference.path === 'ProjectTests/SnapshotTest.swift',\n ),\n ).toHaveLength(1);\n });\n\n it('uses synchronized root group inclusion when the file is inside a target synchronized folder', () => {\n const xcodeProject = new XcodeProject(\n copySingleTargetProjectToTemp('snapshot-source-file-'),\n );\n const filePath = path.join(\n xcodeProject.baseDir,\n 'Sources',\n 'SnapshotTest.swift',\n );\n fs.writeFileSync(filePath, 'import SnapshottingTests\\n', 'utf8');\n\n const result = xcodeProject.addSwiftSourceFileToTarget({\n targetName: 'Project',\n filePath,\n });\n\n expect(result).toEqual({ changed: false, included: true });\n expect(sourceBuildPhaseFiles(xcodeProject)).toEqual([]);\n });\n});\n"]}