@sentry/wizard 6.10.0 → 6.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (144) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/ci-ensure-runtime-loaded.sh +82 -0
  3. package/dist/e2e-tests/tests/angular-17.test.js +72 -82
  4. package/dist/e2e-tests/tests/angular-17.test.js.map +1 -1
  5. package/dist/e2e-tests/tests/angular-19.test.js +71 -80
  6. package/dist/e2e-tests/tests/angular-19.test.js.map +1 -1
  7. package/dist/e2e-tests/tests/cloudflare-worker.test.d.ts +1 -0
  8. package/dist/e2e-tests/tests/cloudflare-worker.test.js +64 -0
  9. package/dist/e2e-tests/tests/cloudflare-worker.test.js.map +1 -0
  10. package/dist/e2e-tests/tests/cloudflare-wrangler-sourcemaps.test.js +2 -5
  11. package/dist/e2e-tests/tests/cloudflare-wrangler-sourcemaps.test.js.map +1 -1
  12. package/dist/e2e-tests/tests/expo.test.js +36 -61
  13. package/dist/e2e-tests/tests/expo.test.js.map +1 -1
  14. package/dist/e2e-tests/tests/flutter.test.js +63 -70
  15. package/dist/e2e-tests/tests/flutter.test.js.map +1 -1
  16. package/dist/e2e-tests/tests/help-message.test.js +2 -2
  17. package/dist/e2e-tests/tests/help-message.test.js.map +1 -1
  18. package/dist/e2e-tests/tests/nextjs-14.test.js +48 -76
  19. package/dist/e2e-tests/tests/nextjs-14.test.js.map +1 -1
  20. package/dist/e2e-tests/tests/nextjs-15.test.js +89 -99
  21. package/dist/e2e-tests/tests/nextjs-15.test.js.map +1 -1
  22. package/dist/e2e-tests/tests/nextjs-16.test.js +48 -45
  23. package/dist/e2e-tests/tests/nextjs-16.test.js.map +1 -1
  24. package/dist/e2e-tests/tests/nuxt-3.test.js +45 -58
  25. package/dist/e2e-tests/tests/nuxt-3.test.js.map +1 -1
  26. package/dist/e2e-tests/tests/nuxt-4.test.js +59 -73
  27. package/dist/e2e-tests/tests/nuxt-4.test.js.map +1 -1
  28. package/dist/e2e-tests/tests/pnpm-workspace.test.js +4 -7
  29. package/dist/e2e-tests/tests/pnpm-workspace.test.js.map +1 -1
  30. package/dist/e2e-tests/tests/react-native.test.js +44 -80
  31. package/dist/e2e-tests/tests/react-native.test.js.map +1 -1
  32. package/dist/e2e-tests/tests/react-router.test.js +163 -145
  33. package/dist/e2e-tests/tests/react-router.test.js.map +1 -1
  34. package/dist/e2e-tests/tests/remix.test.js +162 -132
  35. package/dist/e2e-tests/tests/remix.test.js.map +1 -1
  36. package/dist/e2e-tests/tests/sveltekit-hooks.test.js +48 -36
  37. package/dist/e2e-tests/tests/sveltekit-hooks.test.js.map +1 -1
  38. package/dist/e2e-tests/tests/sveltekit-tracing.test.js +3 -6
  39. package/dist/e2e-tests/tests/sveltekit-tracing.test.js.map +1 -1
  40. package/dist/e2e-tests/utils/index.d.ts +15 -43
  41. package/dist/e2e-tests/utils/index.js +95 -185
  42. package/dist/e2e-tests/utils/index.js.map +1 -1
  43. package/dist/get-e2e-test-matrix.mjs +11 -0
  44. package/dist/lib/Constants.d.ts +1 -0
  45. package/dist/lib/Constants.js +5 -0
  46. package/dist/lib/Constants.js.map +1 -1
  47. package/dist/src/android/android-wizard.js +2 -4
  48. package/dist/src/android/android-wizard.js.map +1 -1
  49. package/dist/src/angular/angular-wizard.js +4 -6
  50. package/dist/src/angular/angular-wizard.js.map +1 -1
  51. package/dist/src/angular/sdk-setup.js +1 -1
  52. package/dist/src/angular/sdk-setup.js.map +1 -1
  53. package/dist/src/apple/apple-wizard.js +2 -4
  54. package/dist/src/apple/apple-wizard.js.map +1 -1
  55. package/dist/src/cloudflare/cloudflare-wizard.d.ts +3 -0
  56. package/dist/src/cloudflare/cloudflare-wizard.js +99 -0
  57. package/dist/src/cloudflare/cloudflare-wizard.js.map +1 -0
  58. package/dist/src/cloudflare/sdk-setup.d.ts +7 -0
  59. package/dist/src/cloudflare/sdk-setup.js +47 -0
  60. package/dist/src/cloudflare/sdk-setup.js.map +1 -0
  61. package/dist/src/cloudflare/templates.d.ts +4 -0
  62. package/dist/src/cloudflare/templates.js +44 -0
  63. package/dist/src/cloudflare/templates.js.map +1 -0
  64. package/dist/src/cloudflare/wrangler/create-wrangler-config.d.ts +4 -0
  65. package/dist/src/cloudflare/wrangler/create-wrangler-config.js +27 -0
  66. package/dist/src/cloudflare/wrangler/create-wrangler-config.js.map +1 -0
  67. package/dist/src/cloudflare/wrangler/ensure-wrangler-config.d.ts +4 -0
  68. package/dist/src/cloudflare/wrangler/ensure-wrangler-config.js +25 -0
  69. package/dist/src/cloudflare/wrangler/ensure-wrangler-config.js.map +1 -0
  70. package/dist/src/cloudflare/wrangler/find-wrangler-config.d.ts +4 -0
  71. package/dist/src/cloudflare/wrangler/find-wrangler-config.js +23 -0
  72. package/dist/src/cloudflare/wrangler/find-wrangler-config.js.map +1 -0
  73. package/dist/src/cloudflare/wrangler/get-entry-point-from-wrangler-config.d.ts +6 -0
  74. package/dist/src/cloudflare/wrangler/get-entry-point-from-wrangler-config.js +52 -0
  75. package/dist/src/cloudflare/wrangler/get-entry-point-from-wrangler-config.js.map +1 -0
  76. package/dist/src/cloudflare/wrangler/update-wrangler-config.d.ts +17 -0
  77. package/dist/src/cloudflare/wrangler/update-wrangler-config.js +173 -0
  78. package/dist/src/cloudflare/wrangler/update-wrangler-config.js.map +1 -0
  79. package/dist/src/cloudflare/wrap-worker.d.ts +32 -0
  80. package/dist/src/cloudflare/wrap-worker.js +109 -0
  81. package/dist/src/cloudflare/wrap-worker.js.map +1 -0
  82. package/dist/src/flutter/flutter-wizard.js +3 -6
  83. package/dist/src/flutter/flutter-wizard.js.map +1 -1
  84. package/dist/src/nextjs/nextjs-wizard.js +0 -2
  85. package/dist/src/nextjs/nextjs-wizard.js.map +1 -1
  86. package/dist/src/nuxt/nuxt-wizard.js +3 -5
  87. package/dist/src/nuxt/nuxt-wizard.js.map +1 -1
  88. package/dist/src/react-native/react-native-wizard.js +2 -4
  89. package/dist/src/react-native/react-native-wizard.js.map +1 -1
  90. package/dist/src/react-router/react-router-wizard.js +3 -5
  91. package/dist/src/react-router/react-router-wizard.js.map +1 -1
  92. package/dist/src/react-router/sdk-setup.d.ts +1 -1
  93. package/dist/src/react-router/sdk-setup.js +3 -4
  94. package/dist/src/react-router/sdk-setup.js.map +1 -1
  95. package/dist/src/remix/remix-wizard.js +2 -4
  96. package/dist/src/remix/remix-wizard.js.map +1 -1
  97. package/dist/src/run.d.ts +1 -1
  98. package/dist/src/run.js +5 -0
  99. package/dist/src/run.js.map +1 -1
  100. package/dist/src/sveltekit/sveltekit-wizard.js +2 -4
  101. package/dist/src/sveltekit/sveltekit-wizard.js.map +1 -1
  102. package/dist/src/utils/abort-if-sportlight-not-supported.d.ts +5 -0
  103. package/dist/src/utils/abort-if-sportlight-not-supported.js +40 -0
  104. package/dist/src/utils/abort-if-sportlight-not-supported.js.map +1 -0
  105. package/dist/src/utils/ast-utils.d.ts +1 -1
  106. package/dist/src/utils/ast-utils.js.map +1 -1
  107. package/dist/src/utils/clack/index.d.ts +2 -2
  108. package/dist/src/utils/clack/index.js.map +1 -1
  109. package/dist/src/utils/clack/mcp-config.js +117 -59
  110. package/dist/src/utils/clack/mcp-config.js.map +1 -1
  111. package/dist/src/version.d.ts +1 -1
  112. package/dist/src/version.js +1 -1
  113. package/dist/src/version.js.map +1 -1
  114. package/dist/test/angular/angular-wizard.test.js +2 -4
  115. package/dist/test/angular/angular-wizard.test.js.map +1 -1
  116. package/dist/test/cloudflare/create-wrangler-config.test.d.ts +1 -0
  117. package/dist/test/cloudflare/create-wrangler-config.test.js +48 -0
  118. package/dist/test/cloudflare/create-wrangler-config.test.js.map +1 -0
  119. package/dist/test/cloudflare/ensure-wrangler-config.test.d.ts +1 -0
  120. package/dist/test/cloudflare/ensure-wrangler-config.test.js +61 -0
  121. package/dist/test/cloudflare/ensure-wrangler-config.test.js.map +1 -0
  122. package/dist/test/cloudflare/find-wrangler-config.test.d.ts +1 -0
  123. package/dist/test/cloudflare/find-wrangler-config.test.js +77 -0
  124. package/dist/test/cloudflare/find-wrangler-config.test.js.map +1 -0
  125. package/dist/test/cloudflare/get-entry-point-from-wrangler-config.test.d.ts +1 -0
  126. package/dist/test/cloudflare/get-entry-point-from-wrangler-config.test.js +81 -0
  127. package/dist/test/cloudflare/get-entry-point-from-wrangler-config.test.js.map +1 -0
  128. package/dist/test/cloudflare/sdk-setup.test.d.ts +1 -0
  129. package/dist/test/cloudflare/sdk-setup.test.js +152 -0
  130. package/dist/test/cloudflare/sdk-setup.test.js.map +1 -0
  131. package/dist/test/cloudflare/templates.test.d.ts +1 -0
  132. package/dist/test/cloudflare/templates.test.js +68 -0
  133. package/dist/test/cloudflare/templates.test.js.map +1 -0
  134. package/dist/test/cloudflare/update-wrangler-config.test.d.ts +1 -0
  135. package/dist/test/cloudflare/update-wrangler-config.test.js +216 -0
  136. package/dist/test/cloudflare/update-wrangler-config.test.js.map +1 -0
  137. package/dist/test/cloudflare/wrap-worker.test.d.ts +1 -0
  138. package/dist/test/cloudflare/wrap-worker.test.js +143 -0
  139. package/dist/test/cloudflare/wrap-worker.test.js.map +1 -0
  140. package/dist/test/react-router/sdk-setup.test.js +2 -2
  141. package/dist/test/react-router/sdk-setup.test.js.map +1 -1
  142. package/dist/test/utils/clack/mcp-config.test.js +176 -51
  143. package/dist/test/utils/clack/mcp-config.test.js.map +1 -1
  144. package/package.json +5 -4
package/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # Changelog
2
2
 
3
+ ## 6.11.0
4
+
5
+ ### New Features
6
+
7
+ #### Cloudflare
8
+
9
+ - Support wrapping workers main file by @JPeer264 in [#1156](https://github.com/getsentry/sentry-wizard/pull/1156)
10
+ - Enable update of the wrangler file by @JPeer264 in [#1149](https://github.com/getsentry/sentry-wizard/pull/1149)
11
+ - Add a basic skeleton for cloudflare by @JPeer264 in [#1147](https://github.com/getsentry/sentry-wizard/pull/1147)
12
+
13
+ #### Mcp
14
+
15
+ - Add multi-select support for MCP configuration by @cursor in [#1153](https://github.com/getsentry/sentry-wizard/pull/1153)
16
+ - Add OpenCode as MCP server provider option by @codyde in [#1154](https://github.com/getsentry/sentry-wizard/pull/1154)
17
+
18
+ ### Bug Fixes
19
+
20
+ - (next) Remove Turbopack outro warning by @logaretm in [#1173](https://github.com/getsentry/sentry-wizard/pull/1173)
21
+ - (react-router) Avoid force-running npx react-router reveal by @Lms24 in [#1181](https://github.com/getsentry/sentry-wizard/pull/1181)
22
+
3
23
  ## 6.10.0
4
24
 
5
25
  - chore(deps): Upgrade `@sentry/node` from v7 to v10.29.0 ([#1126](https://github.com/getsentry/sentry-wizard/pull/1126))
@@ -0,0 +1,82 @@
1
+ #!/bin/bash
2
+
3
+ # This script ensures that a required runtime is loaded.
4
+ #
5
+ # Primary use cases:
6
+ # 1. CI sometimes is failing to load some runtimes, this will ensure they are loaded
7
+
8
+ set -euo pipefail
9
+
10
+ # Parse named arguments
11
+ OS_VERSION=""
12
+ PLATFORM=""
13
+
14
+ usage() {
15
+ echo "Usage: $0 --os-version <os_version> --platform <platform>"
16
+ echo " OS version: Version to ensure is loaded (e.g., 26.1 for beta, 16.4 for older iOS)"
17
+ echo " Platform: Platform to ensure is loaded (e.g., iOS, tvOS, visionOS)"
18
+ echo " Example: $0 --os-version 26.1 --platform iOS"
19
+ echo " Example: $0 --os-version 16.4"
20
+ exit 1
21
+ }
22
+
23
+ while [[ $# -gt 0 ]]; do
24
+ case $1 in
25
+ --os-version)
26
+ OS_VERSION="$2"
27
+ shift 2
28
+ ;;
29
+ --platform)
30
+ PLATFORM="$2"
31
+ shift 2
32
+ ;;
33
+ *)
34
+ echo "Unknown argument: $1"
35
+ usage
36
+ ;;
37
+ esac
38
+ done
39
+
40
+ if [ -z "$OS_VERSION" ]; then
41
+ echo "Error: --os-version argument is required"
42
+ usage
43
+ fi
44
+
45
+ if [ -z "$PLATFORM" ]; then
46
+ echo "Error: --platform argument is required"
47
+ usage
48
+ fi
49
+
50
+ echo "Ensuring runtime $PLATFORM ($OS_VERSION) is loaded"
51
+
52
+ # Check if the runtime is loaded
53
+ if xcrun simctl list runtimes -v | grep -qE "$PLATFORM $OS_VERSION" && ! xcrun simctl list runtimes -v | grep -qE "$PLATFORM $OS_VERSION.*unavailable" ; then
54
+ echo "Runtime $OS_VERSION is loaded"
55
+ exit 0
56
+ fi
57
+
58
+ echo "Runtime $PLATFORM ($OS_VERSION) is not loaded, will try to load it"
59
+
60
+ # Unmount simulator volumes once before checking
61
+ for dir in /Library/Developer/CoreSimulator/Volumes/*; do
62
+ echo "Ejecting $dir"
63
+ sudo diskutil unmount force "$dir" || true
64
+ done
65
+ sudo launchctl kill -9 system/com.apple.CoreSimulator.simdiskimaged || true
66
+ sudo pkill -9 com.apple.CoreSimulator.CoreSimulatorService || true
67
+
68
+ # Wait for a runtime to be loaded
69
+ count=0
70
+ MAX_ATTEMPTS=60 # 300 seconds (5 minutes) timeout
71
+ while [ $count -lt $MAX_ATTEMPTS ]; do
72
+ if xcrun simctl list runtimes -v | grep -qE "$PLATFORM $OS_VERSION" && ! xcrun simctl list runtimes -v | grep -qE "$PLATFORM $OS_VERSION.*unavailable"; then
73
+ echo "Runtime $OS_VERSION is loaded after $count attempts"
74
+ exit 0
75
+ fi
76
+ echo "Waiting for runtime $OS_VERSION to be loaded... attempt $count"
77
+ count=$((count + 1))
78
+ sleep 5
79
+ done
80
+
81
+ echo "Runtime $PLATFORM ($OS_VERSION) is not loaded after $count attempts"
82
+ exit 1
@@ -28,26 +28,30 @@ const utils_1 = require("../utils");
28
28
  const path = __importStar(require("path"));
29
29
  const utils_2 = require("../utils");
30
30
  const vitest_1 = require("vitest");
31
- vitest_1.describe.sequential('Angular-17', () => {
31
+ //@ts-expect-error - clifty is ESM only
32
+ const clifty_1 = require("clifty");
33
+ (0, vitest_1.describe)('Angular-17', () => {
32
34
  (0, vitest_1.describe)('with empty project', () => {
33
35
  const integration = Constants_1.Integration.angular;
34
- const projectDir = path.resolve(__dirname, '../test-applications/angular-17-test-app');
36
+ let wizardExitCode;
37
+ const { projectDir, cleanup } = (0, utils_1.createIsolatedTestEnv)('angular-17-test-app');
35
38
  (0, vitest_1.beforeAll)(async () => {
36
- (0, utils_1.revertLocalChanges)(projectDir);
37
- await runWizardOnAngularProject(projectDir, integration);
39
+ wizardExitCode = await runWizardOnAngularProject(projectDir, integration);
38
40
  });
39
41
  (0, vitest_1.afterAll)(() => {
40
- (0, utils_1.revertLocalChanges)(projectDir);
41
- (0, utils_1.cleanupGit)(projectDir);
42
+ cleanup();
43
+ });
44
+ (0, vitest_1.it)('exits with exit code 0', () => {
45
+ (0, vitest_1.expect)(wizardExitCode).toBe(0);
42
46
  });
43
47
  checkAngularProject(projectDir, integration);
44
48
  });
45
49
  (0, vitest_1.describe)('with pre-defined ErrorHandler', () => {
46
50
  const integration = Constants_1.Integration.angular;
47
- const projectDir = path.resolve(__dirname, '../test-applications/angular-17-test-app');
51
+ let wizardExitCode;
52
+ const { projectDir, cleanup } = (0, utils_1.createIsolatedTestEnv)('angular-17-test-app');
48
53
  (0, vitest_1.beforeAll)(async () => {
49
- (0, utils_1.revertLocalChanges)(projectDir);
50
- await runWizardOnAngularProject(projectDir, integration, (projectDir) => {
54
+ wizardExitCode = await runWizardOnAngularProject(projectDir, integration, (projectDir) => {
51
55
  (0, utils_1.modifyFile)(`${projectDir}/src/app/app.config.ts`, {
52
56
  'providers: [': `providers: [{
53
57
  provide: ErrorHandler,
@@ -58,8 +62,10 @@ vitest_1.describe.sequential('Angular-17', () => {
58
62
  });
59
63
  });
60
64
  (0, vitest_1.afterAll)(() => {
61
- (0, utils_1.revertLocalChanges)(projectDir);
62
- (0, utils_1.cleanupGit)(projectDir);
65
+ cleanup();
66
+ });
67
+ (0, vitest_1.it)('exits with exit code 0', () => {
68
+ (0, vitest_1.expect)(wizardExitCode).toBe(0);
63
69
  });
64
70
  checkAngularProject(projectDir, integration, {
65
71
  preExistingErrorHandler: true,
@@ -67,92 +73,76 @@ vitest_1.describe.sequential('Angular-17', () => {
67
73
  });
68
74
  });
69
75
  async function runWizardOnAngularProject(projectDir, integration, fileModificationFn) {
70
- const wizardInstance = (0, utils_1.startWizardInstance)(integration, projectDir, true);
76
+ const wizardInteraction = (0, clifty_1.withEnv)({
77
+ cwd: projectDir,
78
+ }).defineInteraction();
71
79
  if (fileModificationFn) {
72
80
  fileModificationFn(projectDir);
73
- await wizardInstance.waitForOutput('Do you want to continue anyway?');
74
- await wizardInstance.sendStdinAndWaitForOutput([utils_1.KEYS.ENTER], 'Please select your package manager.');
81
+ wizardInteraction
82
+ .whenAsked('Do you want to continue anyway?')
83
+ .respondWith(clifty_1.KEYS.ENTER);
75
84
  }
76
- else {
77
- await wizardInstance.waitForOutput('Please select your package manager.');
78
- }
79
- await wizardInstance.sendStdinAndWaitForOutput(
80
- // Selecting `yarn v1` as the package manager
81
- [utils_1.KEYS.DOWN, utils_1.KEYS.ENTER],
82
- // "Do you want to enable Tracing", sometimes doesn't work as `Tracing` can be printed in bold.
83
- 'to track the performance of your application?', {
85
+ return (wizardInteraction
86
+ .whenAsked('Please select your package manager.')
87
+ .respondWith(clifty_1.KEYS.ENTER) // npm is the default for Angular
88
+ .expectOutput('Installing @sentry/angular')
89
+ // Installing the sdk can take a while in CI
90
+ .expectOutput('Installed @sentry/angular with NPM.', {
84
91
  timeout: 240000,
85
- optional: true,
86
- });
87
- await wizardInstance.sendStdinAndWaitForOutput(
88
- // select "Yes" for tracing
89
- [utils_1.KEYS.ENTER],
90
- // "Do you want to enable Sentry Session Replay", sometimes doesn't work as `Sentry Session Replay` can be printed in bold.
91
- 'to get a video-like reproduction of errors during a user session?');
92
- await wizardInstance.sendStdinAndWaitForOutput(
93
- // select "Yes" for replay
94
- [utils_1.KEYS.ENTER],
95
- // "Do you want to enable Logs", sometimes doesn't work as `Logs` can be printed in bold.
96
- 'to send your application logs to Sentry?');
97
- await wizardInstance.sendStdinAndWaitForOutput(
98
- // select "Yes" for logs
99
- [utils_1.KEYS.ENTER], 'Where are your build artifacts located?', {
100
- timeout: 240000, // installing Sentry CLI can take a while
101
- });
102
- const sourcemapsConfiguredPromise = wizardInstance.waitForOutput('Added a sentry:sourcemaps script to your package.json');
103
- const buildScriptPromptedPromise = wizardInstance.waitForOutput('Do you want to automatically run the sentry:sourcemaps script after each production build?');
104
- const optionalArtifactsNotFoundPromise = wizardInstance.waitForOutput("We couldn't find build artifacts at", {
105
- optional: true,
106
- timeout: 5000,
107
- });
108
- // ./dist is the default value, no need to change it
109
- wizardInstance.sendStdin(utils_1.KEYS.ENTER);
110
- const optionalArtifactsNotFoundPrompted = await optionalArtifactsNotFoundPromise;
111
- if (optionalArtifactsNotFoundPrompted) {
112
- // The wizard now presents options when artifacts aren't found:
113
- // - "Let the wizard run the build command"
114
- // - "Enter a different path manually"
115
- // - "Proceed anyway — I believe the path is correct"
116
- // We want to select "Proceed anyway" (third option)
117
- wizardInstance.sendStdin(utils_1.KEYS.DOWN);
118
- wizardInstance.sendStdin(utils_1.KEYS.DOWN);
119
- wizardInstance.sendStdin(utils_1.KEYS.ENTER);
120
- }
121
- await sourcemapsConfiguredPromise;
122
- await buildScriptPromptedPromise;
123
- await wizardInstance.sendStdinAndWaitForOutput([utils_1.KEYS.ENTER], // yes, automatically add sentry:sourcemaps script
124
- 'Is yarn build your production build command?');
125
- await wizardInstance.sendStdinAndWaitForOutput([utils_1.KEYS.ENTER], // yes, yarn build is the production build command
126
- 'Are you using a CI/CD tool to build and deploy your application?');
127
- await wizardInstance.sendStdinAndWaitForOutput([utils_1.KEYS.DOWN, utils_1.KEYS.ENTER], // no CI/CD tool
128
- 'Do you want to create an example component to test your Sentry setup?');
129
- await wizardInstance.sendStdinAndWaitForOutput([utils_1.KEYS.ENTER], // yes, create example component
130
- 'Did you apply the snippet above?');
131
- await wizardInstance.sendStdinAndWaitForOutput([utils_1.KEYS.ENTER], // yes, applied the snippet
132
- 'Looks like you have Prettier in your project. Do you want to run it on your files?');
133
- await wizardInstance.sendStdinAndWaitForOutput([utils_1.KEYS.ENTER], // yes, run prettier
134
- 'Optionally add a project-scoped MCP server configuration for the Sentry MCP?', {
135
- optional: true,
136
- });
137
- // Handle the MCP prompt (default is now Yes, so press DOWN to select No)
138
- await wizardInstance.sendStdinAndWaitForOutput([utils_1.KEYS.DOWN, utils_1.KEYS.ENTER], // decline MCP config
139
- 'Successfully installed the Sentry Angular SDK!');
140
- wizardInstance.kill();
92
+ })
93
+ .whenAsked('Do you want to enable Tracing')
94
+ .respondWith(clifty_1.KEYS.ENTER) // yes
95
+ .whenAsked('Do you want to enable Session Replay')
96
+ .respondWith(clifty_1.KEYS.ENTER) // yes
97
+ .whenAsked('Do you want to enable Logs')
98
+ .respondWith(clifty_1.KEYS.ENTER) // yes
99
+ .expectOutput('initialized Sentry in main.ts', {
100
+ timeout: 10000,
101
+ })
102
+ .expectOutput('updated your app config app.config.ts')
103
+ .expectOutput('Installing @sentry/cli')
104
+ .expectOutput('Installed @sentry/cli@', {
105
+ timeout: 240000, // installing Sentry CLI can take a while in CI
106
+ })
107
+ .whenAsked('Where are your build artifacts located?')
108
+ .respondWith(clifty_1.KEYS.ENTER) // ./dist is the default value
109
+ .whenAsked('We couldn\'t find build artifacts at "./dist". What would you like to do?')
110
+ .respondWith(clifty_1.KEYS.DOWN, clifty_1.KEYS.DOWN, clifty_1.KEYS.ENTER) // Proceed anyway (this is expected)
111
+ .whenAsked('Do you want to automatically run the sentry:sourcemaps script after each production build?')
112
+ .respondWith(clifty_1.KEYS.DOWN, clifty_1.KEYS.ENTER) // no - we can't upload in CI when testing building
113
+ .whenAsked('Are you using a CI/CD tool to build and deploy your application?')
114
+ .respondWith(clifty_1.KEYS.ENTER)
115
+ .whenAsked('Add a step to your CI pipeline that runs the sentry:sourcemaps script right after building your application')
116
+ .respondWith(clifty_1.KEYS.ENTER)
117
+ .expectOutput('Add the Sentry authentication token as an environment variable to your CI setup:')
118
+ .expectOutput('SENTRY_AUTH_TOKEN=')
119
+ .whenAsked('Did you configure CI as shown above?')
120
+ .respondWith(clifty_1.KEYS.ENTER) // yes
121
+ .whenAsked('Do you want to create an example component to test your Sentry setup?')
122
+ .respondWith(clifty_1.KEYS.ENTER)
123
+ .whenAsked('Did you apply the snippet above?')
124
+ .respondWith(clifty_1.KEYS.ENTER)
125
+ .whenAsked('Looks like you have Prettier in your project. Do you want to run it on your files?')
126
+ .respondWith(clifty_1.KEYS.ENTER)
127
+ .whenAsked('Optionally add a project-scoped MCP server configuration for the Sentry MCP?')
128
+ .respondWith(clifty_1.KEYS.DOWN, clifty_1.KEYS.ENTER)
129
+ .expectOutput('Successfully installed the Sentry Angular SDK!')
130
+ .run((0, utils_1.getWizardCommand)(integration)));
141
131
  }
142
132
  function checkAngularProject(projectDir, integration, options) {
143
133
  (0, vitest_1.test)('package.json is updated correctly', () => {
144
- (0, utils_1.checkPackageJson)(projectDir, integration);
134
+ (0, utils_1.checkPackageJson)(projectDir, '@sentry/angular');
145
135
  const packageJsonFile = path.resolve(projectDir, 'package.json');
146
136
  (0, utils_1.checkFileContents)(packageJsonFile, [
147
137
  `"sentry:sourcemaps": "sentry-cli sourcemaps inject --org ${utils_2.TEST_ARGS.ORG_SLUG} --project ${utils_2.TEST_ARGS.PROJECT_SLUG} ./dist && sentry-cli sourcemaps upload --org ${utils_2.TEST_ARGS.ORG_SLUG} --project ${utils_2.TEST_ARGS.PROJECT_SLUG} ./dist"`,
148
- `"build": "ng build && yarn sentry:sourcemaps"`,
138
+ `"build": "ng build"`,
149
139
  ]);
150
140
  });
151
141
  (0, vitest_1.test)('Sentry is correctly injected into Angular app config', () => {
152
142
  const appConfigFile = path.resolve(projectDir, 'src/main.ts');
153
143
  (0, utils_1.checkFileExists)(appConfigFile);
154
144
  (0, utils_1.checkFileContents)(appConfigFile, [
155
- `import * as Sentry from '@sentry/angular'`,
145
+ `import * as Sentry from "@sentry/angular";`,
156
146
  'Sentry.init({',
157
147
  utils_2.TEST_ARGS.PROJECT_DSN,
158
148
  'Sentry.browserTracingIntegration()',
@@ -173,7 +163,7 @@ function checkAngularProject(projectDir, integration, options) {
173
163
  (0, utils_1.checkFileDoesNotContain)(appModuleFile, 'Sentry.createErrorHandler()');
174
164
  }
175
165
  (0, utils_1.checkFileContents)(appModuleFile, [
176
- `import * as Sentry from '@sentry/angular'`,
166
+ `import * as Sentry from "@sentry/angular";`,
177
167
  options?.preExistingErrorHandler
178
168
  ? `provide: ErrorHandler,
179
169
  useValue: null`
@@ -1 +1 @@
1
- {"version":3,"file":"angular-17.test.js","sourceRoot":"","sources":["../../../e2e-tests/tests/angular-17.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { Integration } from '../../lib/Constants';\nimport {\n checkFileContents,\n checkFileDoesNotContain,\n checkFileExists,\n checkIfBuilds,\n checkIfRunsOnDevMode,\n checkIfRunsOnProdMode,\n checkPackageJson,\n cleanupGit,\n KEYS,\n modifyFile,\n revertLocalChanges,\n startWizardInstance,\n} from '../utils';\nimport * as path from 'path';\nimport { TEST_ARGS } from '../utils';\nimport { test, expect, describe, beforeAll, afterAll } from 'vitest';\n\ndescribe.sequential('Angular-17', () => {\n describe('with empty project', () => {\n const integration = Integration.angular;\n const projectDir = path.resolve(\n __dirname,\n '../test-applications/angular-17-test-app',\n );\n\n beforeAll(async () => {\n revertLocalChanges(projectDir);\n await runWizardOnAngularProject(projectDir, integration);\n });\n\n afterAll(() => {\n revertLocalChanges(projectDir);\n cleanupGit(projectDir);\n });\n\n checkAngularProject(projectDir, integration);\n });\n\n describe('with pre-defined ErrorHandler', () => {\n const integration = Integration.angular;\n const projectDir = path.resolve(\n __dirname,\n '../test-applications/angular-17-test-app',\n );\n\n beforeAll(async () => {\n revertLocalChanges(projectDir);\n await runWizardOnAngularProject(projectDir, integration, (projectDir) => {\n modifyFile(`${projectDir}/src/app/app.config.ts`, {\n 'providers: [': `providers: [{\n provide: ErrorHandler,\n useValue: null\n },\n `,\n });\n });\n });\n\n afterAll(() => {\n revertLocalChanges(projectDir);\n cleanupGit(projectDir);\n });\n\n checkAngularProject(projectDir, integration, {\n preExistingErrorHandler: true,\n });\n });\n});\n\nasync function runWizardOnAngularProject(\n projectDir: string,\n integration: Integration,\n fileModificationFn?: (projectDir: string) => unknown,\n) {\n const wizardInstance = startWizardInstance(integration, projectDir, true);\n\n if (fileModificationFn) {\n fileModificationFn(projectDir);\n\n await wizardInstance.waitForOutput('Do you want to continue anyway?');\n\n await wizardInstance.sendStdinAndWaitForOutput(\n [KEYS.ENTER],\n 'Please select your package manager.',\n );\n } else {\n await wizardInstance.waitForOutput('Please select your package manager.');\n }\n\n await wizardInstance.sendStdinAndWaitForOutput(\n // Selecting `yarn v1` as the package manager\n [KEYS.DOWN, KEYS.ENTER],\n // \"Do you want to enable Tracing\", sometimes doesn't work as `Tracing` can be printed in bold.\n 'to track the performance of your application?',\n {\n timeout: 240_000, // installing the sdk can take a while\n optional: true,\n },\n );\n\n await wizardInstance.sendStdinAndWaitForOutput(\n // select \"Yes\" for tracing\n [KEYS.ENTER],\n // \"Do you want to enable Sentry Session Replay\", sometimes doesn't work as `Sentry Session Replay` can be printed in bold.\n 'to get a video-like reproduction of errors during a user session?',\n );\n\n await wizardInstance.sendStdinAndWaitForOutput(\n // select \"Yes\" for replay\n [KEYS.ENTER],\n // \"Do you want to enable Logs\", sometimes doesn't work as `Logs` can be printed in bold.\n 'to send your application logs to Sentry?',\n );\n\n await wizardInstance.sendStdinAndWaitForOutput(\n // select \"Yes\" for logs\n [KEYS.ENTER],\n 'Where are your build artifacts located?',\n {\n timeout: 240_000, // installing Sentry CLI can take a while\n },\n );\n\n const sourcemapsConfiguredPromise = wizardInstance.waitForOutput(\n 'Added a sentry:sourcemaps script to your package.json',\n );\n\n const buildScriptPromptedPromise = wizardInstance.waitForOutput(\n 'Do you want to automatically run the sentry:sourcemaps script after each production build?',\n );\n\n const optionalArtifactsNotFoundPromise = wizardInstance.waitForOutput(\n \"We couldn't find build artifacts at\",\n {\n optional: true,\n timeout: 5000,\n },\n );\n\n // ./dist is the default value, no need to change it\n wizardInstance.sendStdin(KEYS.ENTER);\n\n const optionalArtifactsNotFoundPrompted =\n await optionalArtifactsNotFoundPromise;\n\n if (optionalArtifactsNotFoundPrompted) {\n // The wizard now presents options when artifacts aren't found:\n // - \"Let the wizard run the build command\"\n // - \"Enter a different path manually\"\n // - \"Proceed anyway — I believe the path is correct\"\n // We want to select \"Proceed anyway\" (third option)\n wizardInstance.sendStdin(KEYS.DOWN);\n wizardInstance.sendStdin(KEYS.DOWN);\n wizardInstance.sendStdin(KEYS.ENTER);\n }\n\n await sourcemapsConfiguredPromise;\n\n await buildScriptPromptedPromise;\n\n await wizardInstance.sendStdinAndWaitForOutput(\n [KEYS.ENTER], // yes, automatically add sentry:sourcemaps script\n 'Is yarn build your production build command?',\n );\n\n await wizardInstance.sendStdinAndWaitForOutput(\n [KEYS.ENTER], // yes, yarn build is the production build command\n 'Are you using a CI/CD tool to build and deploy your application?',\n );\n\n await wizardInstance.sendStdinAndWaitForOutput(\n [KEYS.DOWN, KEYS.ENTER], // no CI/CD tool\n 'Do you want to create an example component to test your Sentry setup?',\n );\n\n await wizardInstance.sendStdinAndWaitForOutput(\n [KEYS.ENTER], // yes, create example component\n 'Did you apply the snippet above?',\n );\n\n await wizardInstance.sendStdinAndWaitForOutput(\n [KEYS.ENTER], // yes, applied the snippet\n 'Looks like you have Prettier in your project. Do you want to run it on your files?',\n );\n\n await wizardInstance.sendStdinAndWaitForOutput(\n [KEYS.ENTER], // yes, run prettier\n 'Optionally add a project-scoped MCP server configuration for the Sentry MCP?',\n {\n optional: true,\n },\n );\n\n // Handle the MCP prompt (default is now Yes, so press DOWN to select No)\n await wizardInstance.sendStdinAndWaitForOutput(\n [KEYS.DOWN, KEYS.ENTER], // decline MCP config\n 'Successfully installed the Sentry Angular SDK!',\n );\n\n wizardInstance.kill();\n}\n\nfunction checkAngularProject(\n projectDir: string,\n integration: Integration,\n options?: {\n preExistingErrorHandler?: boolean;\n },\n) {\n test('package.json is updated correctly', () => {\n checkPackageJson(projectDir, integration);\n\n const packageJsonFile = path.resolve(projectDir, 'package.json');\n checkFileContents(packageJsonFile, [\n `\"sentry:sourcemaps\": \"sentry-cli sourcemaps inject --org ${TEST_ARGS.ORG_SLUG} --project ${TEST_ARGS.PROJECT_SLUG} ./dist && sentry-cli sourcemaps upload --org ${TEST_ARGS.ORG_SLUG} --project ${TEST_ARGS.PROJECT_SLUG} ./dist\"`,\n `\"build\": \"ng build && yarn sentry:sourcemaps\"`,\n ]);\n });\n\n test('Sentry is correctly injected into Angular app config', () => {\n const appConfigFile = path.resolve(projectDir, 'src/main.ts');\n checkFileExists(appConfigFile);\n\n checkFileContents(appConfigFile, [\n `import * as Sentry from '@sentry/angular'`,\n 'Sentry.init({',\n TEST_ARGS.PROJECT_DSN,\n 'Sentry.browserTracingIntegration()',\n 'Sentry.replayIntegration()',\n 'tracesSampleRate: 1',\n 'replaysSessionSampleRate: 0.1',\n 'replaysOnErrorSampleRate: 1',\n 'enableLogs: true',\n 'sendDefaultPii: true',\n ]);\n });\n\n test('Sentry is correctly injected into Angular app module', () => {\n const appModuleFile = path.resolve(projectDir, 'src/app/app.config.ts');\n checkFileExists(appModuleFile);\n\n // Checking if the ErrorHandler is already present in the providers array,\n // and if it is, we skip adding it\n if (options?.preExistingErrorHandler) {\n checkFileDoesNotContain(appModuleFile, 'Sentry.createErrorHandler()');\n }\n\n checkFileContents(appModuleFile, [\n `import * as Sentry from '@sentry/angular'`,\n options?.preExistingErrorHandler\n ? `provide: ErrorHandler,\n useValue: null`\n : `provide: ErrorHandler,\n useValue: Sentry.createErrorHandler()`,\n `provide: Sentry.TraceService,\n deps: [Router]`,\n `provide: APP_INITIALIZER,\n useFactory: () => () => {},\n deps: [Sentry.TraceService],\n multi: true`,\n ]);\n });\n\n test('angular.json is updated correctly', async () => {\n const angularJsonFile = path.resolve(projectDir, 'angular.json');\n checkFileExists(angularJsonFile);\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const angularJson = (await import(angularJsonFile)) as Record<string, any>;\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n for (const [, project] of Object.entries(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n angularJson.projects as Record<string, any>,\n )) {\n expect(\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n project?.architect?.build?.configurations?.production?.sourceMap,\n ).toBe(true);\n }\n });\n\n test('builds successfully', async () => {\n await checkIfBuilds(projectDir);\n });\n\n test('runs on prod mode correctly', async () => {\n await checkIfRunsOnProdMode(\n projectDir,\n 'Application bundle generation complete.',\n );\n });\n\n test('runs on dev mode correctly', async () => {\n await checkIfRunsOnDevMode(\n projectDir,\n 'Application bundle generation complete.',\n );\n });\n}\n"]}
1
+ {"version":3,"file":"angular-17.test.js","sourceRoot":"","sources":["../../../e2e-tests/tests/angular-17.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { Integration } from '../../lib/Constants';\nimport {\n checkFileContents,\n checkFileDoesNotContain,\n checkFileExists,\n checkIfBuilds,\n checkIfRunsOnDevMode,\n checkIfRunsOnProdMode,\n checkPackageJson,\n createIsolatedTestEnv,\n getWizardCommand,\n modifyFile,\n} from '../utils';\nimport * as path from 'path';\nimport { TEST_ARGS } from '../utils';\nimport { test, expect, describe, beforeAll, afterAll, it } from 'vitest';\n\n//@ts-expect-error - clifty is ESM only\nimport { KEYS, withEnv } from 'clifty';\n\ndescribe('Angular-17', () => {\n describe('with empty project', () => {\n const integration = Integration.angular;\n let wizardExitCode: number;\n\n const { projectDir, cleanup } = createIsolatedTestEnv(\n 'angular-17-test-app',\n );\n\n beforeAll(async () => {\n wizardExitCode = await runWizardOnAngularProject(projectDir, integration);\n });\n\n afterAll(() => {\n cleanup();\n });\n\n it('exits with exit code 0', () => {\n expect(wizardExitCode).toBe(0);\n });\n\n checkAngularProject(projectDir, integration);\n });\n\n describe('with pre-defined ErrorHandler', () => {\n const integration = Integration.angular;\n let wizardExitCode: number;\n\n const { projectDir, cleanup } = createIsolatedTestEnv(\n 'angular-17-test-app',\n );\n\n beforeAll(async () => {\n wizardExitCode = await runWizardOnAngularProject(\n projectDir,\n integration,\n (projectDir) => {\n modifyFile(`${projectDir}/src/app/app.config.ts`, {\n 'providers: [': `providers: [{\n provide: ErrorHandler,\n useValue: null\n },\n `,\n });\n },\n );\n });\n\n afterAll(() => {\n cleanup();\n });\n\n it('exits with exit code 0', () => {\n expect(wizardExitCode).toBe(0);\n });\n\n checkAngularProject(projectDir, integration, {\n preExistingErrorHandler: true,\n });\n });\n});\n\nasync function runWizardOnAngularProject(\n projectDir: string,\n integration: Integration,\n fileModificationFn?: (projectDir: string) => unknown,\n): Promise<number> {\n const wizardInteraction = withEnv({\n cwd: projectDir,\n }).defineInteraction();\n\n if (fileModificationFn) {\n fileModificationFn(projectDir);\n\n wizardInteraction\n .whenAsked('Do you want to continue anyway?')\n .respondWith(KEYS.ENTER);\n }\n\n return (\n wizardInteraction\n .whenAsked('Please select your package manager.')\n .respondWith(KEYS.ENTER) // npm is the default for Angular\n .expectOutput('Installing @sentry/angular')\n // Installing the sdk can take a while in CI\n .expectOutput('Installed @sentry/angular with NPM.', {\n timeout: 240_000,\n })\n .whenAsked('Do you want to enable Tracing')\n .respondWith(KEYS.ENTER) // yes\n .whenAsked('Do you want to enable Session Replay')\n .respondWith(KEYS.ENTER) // yes\n .whenAsked('Do you want to enable Logs')\n .respondWith(KEYS.ENTER) // yes\n .expectOutput('initialized Sentry in main.ts', {\n timeout: 10_000,\n })\n .expectOutput('updated your app config app.config.ts')\n .expectOutput('Installing @sentry/cli')\n .expectOutput('Installed @sentry/cli@', {\n timeout: 240_000, // installing Sentry CLI can take a while in CI\n })\n .whenAsked('Where are your build artifacts located?')\n .respondWith(KEYS.ENTER) // ./dist is the default value\n .whenAsked(\n 'We couldn\\'t find build artifacts at \"./dist\". What would you like to do?',\n )\n .respondWith(KEYS.DOWN, KEYS.DOWN, KEYS.ENTER) // Proceed anyway (this is expected)\n .whenAsked(\n 'Do you want to automatically run the sentry:sourcemaps script after each production build?',\n )\n .respondWith(KEYS.DOWN, KEYS.ENTER) // no - we can't upload in CI when testing building\n .whenAsked(\n 'Are you using a CI/CD tool to build and deploy your application?',\n )\n .respondWith(KEYS.ENTER)\n .whenAsked(\n 'Add a step to your CI pipeline that runs the sentry:sourcemaps script right after building your application',\n )\n .respondWith(KEYS.ENTER)\n .expectOutput(\n 'Add the Sentry authentication token as an environment variable to your CI setup:',\n )\n .expectOutput('SENTRY_AUTH_TOKEN=')\n .whenAsked('Did you configure CI as shown above?')\n .respondWith(KEYS.ENTER) // yes\n .whenAsked(\n 'Do you want to create an example component to test your Sentry setup?',\n )\n .respondWith(KEYS.ENTER)\n .whenAsked('Did you apply the snippet above?')\n .respondWith(KEYS.ENTER)\n .whenAsked(\n 'Looks like you have Prettier in your project. Do you want to run it on your files?',\n )\n .respondWith(KEYS.ENTER)\n .whenAsked(\n 'Optionally add a project-scoped MCP server configuration for the Sentry MCP?',\n )\n .respondWith(KEYS.DOWN, KEYS.ENTER)\n .expectOutput('Successfully installed the Sentry Angular SDK!')\n .run(getWizardCommand(integration))\n );\n}\n\nfunction checkAngularProject(\n projectDir: string,\n integration: Integration,\n options?: {\n preExistingErrorHandler?: boolean;\n },\n) {\n test('package.json is updated correctly', () => {\n checkPackageJson(projectDir, '@sentry/angular');\n\n const packageJsonFile = path.resolve(projectDir, 'package.json');\n checkFileContents(packageJsonFile, [\n `\"sentry:sourcemaps\": \"sentry-cli sourcemaps inject --org ${TEST_ARGS.ORG_SLUG} --project ${TEST_ARGS.PROJECT_SLUG} ./dist && sentry-cli sourcemaps upload --org ${TEST_ARGS.ORG_SLUG} --project ${TEST_ARGS.PROJECT_SLUG} ./dist\"`,\n `\"build\": \"ng build\"`,\n ]);\n });\n\n test('Sentry is correctly injected into Angular app config', () => {\n const appConfigFile = path.resolve(projectDir, 'src/main.ts');\n checkFileExists(appConfigFile);\n\n checkFileContents(appConfigFile, [\n `import * as Sentry from \"@sentry/angular\";`,\n 'Sentry.init({',\n TEST_ARGS.PROJECT_DSN,\n 'Sentry.browserTracingIntegration()',\n 'Sentry.replayIntegration()',\n 'tracesSampleRate: 1',\n 'replaysSessionSampleRate: 0.1',\n 'replaysOnErrorSampleRate: 1',\n 'enableLogs: true',\n 'sendDefaultPii: true',\n ]);\n });\n\n test('Sentry is correctly injected into Angular app module', () => {\n const appModuleFile = path.resolve(projectDir, 'src/app/app.config.ts');\n checkFileExists(appModuleFile);\n\n // Checking if the ErrorHandler is already present in the providers array,\n // and if it is, we skip adding it\n if (options?.preExistingErrorHandler) {\n checkFileDoesNotContain(appModuleFile, 'Sentry.createErrorHandler()');\n }\n\n checkFileContents(appModuleFile, [\n `import * as Sentry from \"@sentry/angular\";`,\n options?.preExistingErrorHandler\n ? `provide: ErrorHandler,\n useValue: null`\n : `provide: ErrorHandler,\n useValue: Sentry.createErrorHandler()`,\n `provide: Sentry.TraceService,\n deps: [Router]`,\n `provide: APP_INITIALIZER,\n useFactory: () => () => {},\n deps: [Sentry.TraceService],\n multi: true`,\n ]);\n });\n\n test('angular.json is updated correctly', async () => {\n const angularJsonFile = path.resolve(projectDir, 'angular.json');\n checkFileExists(angularJsonFile);\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const angularJson = (await import(angularJsonFile)) as Record<string, any>;\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n for (const [, project] of Object.entries(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n angularJson.projects as Record<string, any>,\n )) {\n expect(\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n project?.architect?.build?.configurations?.production?.sourceMap,\n ).toBe(true);\n }\n });\n\n test('builds successfully', async () => {\n await checkIfBuilds(projectDir);\n });\n\n test('runs on prod mode correctly', async () => {\n await checkIfRunsOnProdMode(\n projectDir,\n 'Application bundle generation complete.',\n );\n });\n\n test('runs on dev mode correctly', async () => {\n await checkIfRunsOnDevMode(\n projectDir,\n 'Application bundle generation complete.',\n );\n });\n}\n"]}
@@ -28,26 +28,30 @@ const utils_1 = require("../utils");
28
28
  const path = __importStar(require("path"));
29
29
  const utils_2 = require("../utils");
30
30
  const vitest_1 = require("vitest");
31
+ //@ts-expect-error - clifty is ESM only
32
+ const clifty_1 = require("clifty");
31
33
  vitest_1.describe.sequential('Angular-19', () => {
32
34
  (0, vitest_1.describe)('with empty project', () => {
33
35
  const integration = Constants_1.Integration.angular;
34
- const projectDir = path.resolve(__dirname, '../test-applications/angular-19-test-app');
36
+ let wizardExitCode;
37
+ const { projectDir, cleanup } = (0, utils_1.createIsolatedTestEnv)('angular-19-test-app');
35
38
  (0, vitest_1.beforeAll)(async () => {
36
- (0, utils_1.revertLocalChanges)(projectDir);
37
- await runWizardOnAngularProject(projectDir, integration);
39
+ wizardExitCode = await runWizardOnAngularProject(projectDir, integration);
38
40
  });
39
41
  (0, vitest_1.afterAll)(() => {
40
- (0, utils_1.revertLocalChanges)(projectDir);
41
- (0, utils_1.cleanupGit)(projectDir);
42
+ cleanup();
43
+ });
44
+ (0, vitest_1.it)('exits with exit code 0', () => {
45
+ (0, vitest_1.expect)(wizardExitCode).toBe(0);
42
46
  });
43
47
  checkAngularProject(projectDir, integration);
44
48
  });
45
49
  (0, vitest_1.describe)('with pre-defined ErrorHandler', () => {
46
50
  const integration = Constants_1.Integration.angular;
47
- const projectDir = path.resolve(__dirname, '../test-applications/angular-19-test-app');
51
+ let wizardExitCode;
52
+ const { projectDir, cleanup } = (0, utils_1.createIsolatedTestEnv)('angular-19-test-app');
48
53
  (0, vitest_1.beforeAll)(async () => {
49
- (0, utils_1.revertLocalChanges)(projectDir);
50
- await runWizardOnAngularProject(projectDir, integration, (projectDir) => {
54
+ wizardExitCode = await runWizardOnAngularProject(projectDir, integration, (projectDir) => {
51
55
  (0, utils_1.modifyFile)(`${projectDir}/src/app/app.config.ts`, {
52
56
  'providers: [': `providers: [{
53
57
  provide: ErrorHandler,
@@ -58,8 +62,10 @@ vitest_1.describe.sequential('Angular-19', () => {
58
62
  });
59
63
  });
60
64
  (0, vitest_1.afterAll)(() => {
61
- (0, utils_1.revertLocalChanges)(projectDir);
62
- (0, utils_1.cleanupGit)(projectDir);
65
+ cleanup();
66
+ });
67
+ (0, vitest_1.it)('exits with exit code 0', () => {
68
+ (0, vitest_1.expect)(wizardExitCode).toBe(0);
63
69
  });
64
70
  checkAngularProject(projectDir, integration, {
65
71
  preExistingErrorHandler: true,
@@ -67,91 +73,76 @@ vitest_1.describe.sequential('Angular-19', () => {
67
73
  });
68
74
  });
69
75
  async function runWizardOnAngularProject(projectDir, integration, fileModificationFn) {
70
- const wizardInstance = (0, utils_1.startWizardInstance)(integration, projectDir, true);
76
+ const wizardInteraction = (0, clifty_1.withEnv)({
77
+ cwd: projectDir,
78
+ }).defineInteraction();
71
79
  if (fileModificationFn) {
72
80
  fileModificationFn(projectDir);
73
- await wizardInstance.waitForOutput('Do you want to continue anyway?');
74
- await wizardInstance.sendStdinAndWaitForOutput([utils_1.KEYS.ENTER], 'Please select your package manager.');
81
+ wizardInteraction
82
+ .whenAsked('Do you want to continue anyway?')
83
+ .respondWith(clifty_1.KEYS.ENTER);
75
84
  }
76
- else {
77
- await wizardInstance.waitForOutput('Please select your package manager.');
78
- }
79
- await wizardInstance.sendStdinAndWaitForOutput(
80
- // Selecting `yarn` as the package manager
81
- [utils_1.KEYS.DOWN, utils_1.KEYS.ENTER],
82
- // "Do you want to enable Tracing", sometimes doesn't work as `Tracing` can be printed in bold.
83
- 'to track the performance of your application?', {
85
+ return (wizardInteraction
86
+ .whenAsked('Please select your package manager.')
87
+ .respondWith(clifty_1.KEYS.ENTER) // npm is the default for Angular
88
+ .expectOutput('Installing @sentry/angular')
89
+ // Installing the sdk can take a while in CI
90
+ .expectOutput('Installed @sentry/angular with NPM.', {
84
91
  timeout: 240000,
85
- optional: true,
86
- });
87
- await wizardInstance.sendStdinAndWaitForOutput([utils_1.KEYS.ENTER],
88
- // "Do you want to enable Sentry Session Replay", sometimes doesn't work as `Sentry Session Replay` can be printed in bold.
89
- 'to get a video-like reproduction of errors during a user session?');
90
- await wizardInstance.sendStdinAndWaitForOutput(
91
- // select "Yes" for replay
92
- [utils_1.KEYS.ENTER],
93
- // "Do you want to enable Logs", sometimes doesn't work as `Logs` can be printed in bold.
94
- 'to send your application logs to Sentry?');
95
- await wizardInstance.sendStdinAndWaitForOutput(
96
- // select "Yes" for logs
97
- [utils_1.KEYS.ENTER], 'Where are your build artifacts located?', {
98
- optional: true,
99
- timeout: 5000,
100
- });
101
- const sourcemapsConfiguredPromise = wizardInstance.waitForOutput('Added a sentry:sourcemaps script to your package.json');
102
- const buildScriptPromptedPromise = wizardInstance.waitForOutput('Do you want to automatically run the sentry:sourcemaps script after each production build?');
103
- const optionalArtifactsNotFoundPromise = wizardInstance.waitForOutput("We couldn't find build artifacts at", {
104
- optional: true,
105
- timeout: 5000,
106
- });
107
- // ./dist is the default value, no need to change it
108
- wizardInstance.sendStdin(utils_1.KEYS.ENTER);
109
- const optionalArtifactsNotFoundPrompted = await optionalArtifactsNotFoundPromise;
110
- if (optionalArtifactsNotFoundPrompted) {
111
- // The wizard now presents options when artifacts aren't found:
112
- // - "Let the wizard run the build command"
113
- // - "Enter a different path manually"
114
- // - "Proceed anyway I believe the path is correct"
115
- // We want to select "Proceed anyway" (third option)
116
- wizardInstance.sendStdin(utils_1.KEYS.DOWN);
117
- wizardInstance.sendStdin(utils_1.KEYS.DOWN);
118
- wizardInstance.sendStdin(utils_1.KEYS.ENTER);
119
- }
120
- await sourcemapsConfiguredPromise;
121
- await buildScriptPromptedPromise;
122
- await wizardInstance.sendStdinAndWaitForOutput([utils_1.KEYS.ENTER], // yes, automatically add sentry:sourcemaps script
123
- 'Is yarn build your production build command?');
124
- await wizardInstance.sendStdinAndWaitForOutput([utils_1.KEYS.ENTER], // yes, yarn build is the production build command
125
- 'Are you using a CI/CD tool to build and deploy your application?');
126
- await wizardInstance.sendStdinAndWaitForOutput([utils_1.KEYS.DOWN, utils_1.KEYS.ENTER], // no CI/CD tool
127
- 'Do you want to create an example component to test your Sentry setup?');
128
- await wizardInstance.sendStdinAndWaitForOutput([utils_1.KEYS.ENTER], // yes, create example component
129
- 'Did you apply the snippet above?');
130
- await wizardInstance.sendStdinAndWaitForOutput([utils_1.KEYS.ENTER], // yes, applied the snippet
131
- 'Looks like you have Prettier in your project. Do you want to run it on your files?');
132
- await wizardInstance.sendStdinAndWaitForOutput([utils_1.KEYS.ENTER], // yes, run prettier
133
- 'Optionally add a project-scoped MCP server configuration for the Sentry MCP?', {
134
- optional: true,
135
- });
136
- // Handle the MCP prompt (default is now Yes, so press DOWN to select No)
137
- await wizardInstance.sendStdinAndWaitForOutput([utils_1.KEYS.DOWN, utils_1.KEYS.ENTER], // decline MCP config
138
- 'Successfully installed the Sentry Angular SDK!');
139
- wizardInstance.kill();
92
+ })
93
+ .whenAsked('Do you want to enable Tracing')
94
+ .respondWith(clifty_1.KEYS.ENTER) // yes
95
+ .whenAsked('Do you want to enable Session Replay')
96
+ .respondWith(clifty_1.KEYS.ENTER) // yes
97
+ .whenAsked('Do you want to enable Logs')
98
+ .respondWith(clifty_1.KEYS.ENTER) // yes
99
+ .expectOutput('initialized Sentry in main.ts', {
100
+ timeout: 10000,
101
+ })
102
+ .expectOutput('updated your app config app.config.ts')
103
+ .expectOutput('Installing @sentry/cli')
104
+ .expectOutput('Installed @sentry/cli@', {
105
+ timeout: 240000, // installing Sentry CLI can take a while in CI
106
+ })
107
+ .whenAsked('Where are your build artifacts located?')
108
+ .respondWith(clifty_1.KEYS.ENTER) // ./dist is the default value
109
+ .whenAsked('We couldn\'t find build artifacts at "./dist". What would you like to do?')
110
+ .respondWith(clifty_1.KEYS.DOWN, clifty_1.KEYS.DOWN, clifty_1.KEYS.ENTER) // Proceed anyway (this is expected)
111
+ .whenAsked('Do you want to automatically run the sentry:sourcemaps script after each production build?')
112
+ .respondWith(clifty_1.KEYS.DOWN, clifty_1.KEYS.ENTER) // no - we can't upload in CI when testing building
113
+ .whenAsked('Are you using a CI/CD tool to build and deploy your application?')
114
+ .respondWith(clifty_1.KEYS.ENTER)
115
+ .whenAsked('Add a step to your CI pipeline that runs the sentry:sourcemaps script right after building your application')
116
+ .respondWith(clifty_1.KEYS.ENTER)
117
+ .expectOutput('Add the Sentry authentication token as an environment variable to your CI setup:')
118
+ .expectOutput('SENTRY_AUTH_TOKEN=')
119
+ .whenAsked('Did you configure CI as shown above?')
120
+ .respondWith(clifty_1.KEYS.ENTER) // yes
121
+ .whenAsked('Do you want to create an example component to test your Sentry setup?')
122
+ .respondWith(clifty_1.KEYS.ENTER)
123
+ .whenAsked('Did you apply the snippet above?')
124
+ .respondWith(clifty_1.KEYS.ENTER)
125
+ .whenAsked('Looks like you have Prettier in your project. Do you want to run it on your files?')
126
+ .respondWith(clifty_1.KEYS.ENTER)
127
+ .whenAsked('Optionally add a project-scoped MCP server configuration for the Sentry MCP?')
128
+ .respondWith(clifty_1.KEYS.DOWN, clifty_1.KEYS.ENTER)
129
+ .expectOutput('Successfully installed the Sentry Angular SDK!')
130
+ .run((0, utils_1.getWizardCommand)(integration)));
140
131
  }
141
132
  function checkAngularProject(projectDir, integration, options) {
142
133
  (0, vitest_1.test)('package.json is updated correctly', () => {
143
- (0, utils_1.checkPackageJson)(projectDir, integration);
134
+ (0, utils_1.checkPackageJson)(projectDir, '@sentry/angular');
144
135
  const packageJsonFile = path.resolve(projectDir, 'package.json');
145
136
  (0, utils_1.checkFileContents)(packageJsonFile, [
146
137
  `"sentry:sourcemaps": "sentry-cli sourcemaps inject --org ${utils_2.TEST_ARGS.ORG_SLUG} --project ${utils_2.TEST_ARGS.PROJECT_SLUG} ./dist && sentry-cli sourcemaps upload --org ${utils_2.TEST_ARGS.ORG_SLUG} --project ${utils_2.TEST_ARGS.PROJECT_SLUG} ./dist"`,
147
- `"build": "ng build && yarn sentry:sourcemaps"`,
138
+ `"build": "ng build"`,
148
139
  ]);
149
140
  });
150
141
  (0, vitest_1.test)('Sentry is correctly injected into Angular app config', () => {
151
142
  const appConfigFile = path.resolve(projectDir, 'src/main.ts');
152
143
  (0, utils_1.checkFileExists)(appConfigFile);
153
144
  (0, utils_1.checkFileContents)(appConfigFile, [
154
- `import * as Sentry from '@sentry/angular'`,
145
+ `import * as Sentry from "@sentry/angular";`,
155
146
  'Sentry.init({',
156
147
  utils_2.TEST_ARGS.PROJECT_DSN,
157
148
  'Sentry.browserTracingIntegration()',
@@ -172,7 +163,7 @@ function checkAngularProject(projectDir, integration, options) {
172
163
  (0, utils_1.checkFileDoesNotContain)(appModuleFile, 'Sentry.createErrorHandler()');
173
164
  }
174
165
  (0, utils_1.checkFileContents)(appModuleFile, [
175
- `import * as Sentry from '@sentry/angular'`,
166
+ `import * as Sentry from "@sentry/angular";`,
176
167
  options?.preExistingErrorHandler
177
168
  ? `provide: ErrorHandler,
178
169
  useValue: null`