@sentry/wizard 6.9.0 → 6.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (170) hide show
  1. package/CHANGELOG.md +56 -1
  2. package/dist/ci-ensure-runtime-loaded.sh +82 -0
  3. package/dist/e2e-tests/tests/angular-17.test.js +72 -82
  4. package/dist/e2e-tests/tests/angular-17.test.js.map +1 -1
  5. package/dist/e2e-tests/tests/angular-19.test.js +71 -80
  6. package/dist/e2e-tests/tests/angular-19.test.js.map +1 -1
  7. package/dist/e2e-tests/tests/cloudflare-worker.test.d.ts +1 -0
  8. package/dist/e2e-tests/tests/cloudflare-worker.test.js +64 -0
  9. package/dist/e2e-tests/tests/cloudflare-worker.test.js.map +1 -0
  10. package/dist/e2e-tests/tests/cloudflare-wrangler-sourcemaps.test.js +2 -5
  11. package/dist/e2e-tests/tests/cloudflare-wrangler-sourcemaps.test.js.map +1 -1
  12. package/dist/e2e-tests/tests/expo.test.js +36 -61
  13. package/dist/e2e-tests/tests/expo.test.js.map +1 -1
  14. package/dist/e2e-tests/tests/flutter.test.js +63 -70
  15. package/dist/e2e-tests/tests/flutter.test.js.map +1 -1
  16. package/dist/e2e-tests/tests/help-message.test.js +2 -2
  17. package/dist/e2e-tests/tests/help-message.test.js.map +1 -1
  18. package/dist/e2e-tests/tests/nextjs-14.test.js +54 -82
  19. package/dist/e2e-tests/tests/nextjs-14.test.js.map +1 -1
  20. package/dist/e2e-tests/tests/nextjs-15.test.js +95 -105
  21. package/dist/e2e-tests/tests/nextjs-15.test.js.map +1 -1
  22. package/dist/e2e-tests/tests/nextjs-16.test.d.ts +1 -0
  23. package/dist/e2e-tests/tests/nextjs-16.test.js +123 -0
  24. package/dist/e2e-tests/tests/nextjs-16.test.js.map +1 -0
  25. package/dist/e2e-tests/tests/nuxt-3.test.js +45 -58
  26. package/dist/e2e-tests/tests/nuxt-3.test.js.map +1 -1
  27. package/dist/e2e-tests/tests/nuxt-4.test.js +59 -73
  28. package/dist/e2e-tests/tests/nuxt-4.test.js.map +1 -1
  29. package/dist/e2e-tests/tests/pnpm-workspace.test.js +4 -7
  30. package/dist/e2e-tests/tests/pnpm-workspace.test.js.map +1 -1
  31. package/dist/e2e-tests/tests/react-native.test.js +44 -80
  32. package/dist/e2e-tests/tests/react-native.test.js.map +1 -1
  33. package/dist/e2e-tests/tests/react-router.test.js +163 -145
  34. package/dist/e2e-tests/tests/react-router.test.js.map +1 -1
  35. package/dist/e2e-tests/tests/remix.test.js +162 -132
  36. package/dist/e2e-tests/tests/remix.test.js.map +1 -1
  37. package/dist/e2e-tests/tests/sveltekit-hooks.test.js +48 -36
  38. package/dist/e2e-tests/tests/sveltekit-hooks.test.js.map +1 -1
  39. package/dist/e2e-tests/tests/sveltekit-tracing.test.js +3 -6
  40. package/dist/e2e-tests/tests/sveltekit-tracing.test.js.map +1 -1
  41. package/dist/e2e-tests/utils/index.d.ts +21 -43
  42. package/dist/e2e-tests/utils/index.js +108 -183
  43. package/dist/e2e-tests/utils/index.js.map +1 -1
  44. package/dist/get-e2e-test-matrix.mjs +11 -0
  45. package/dist/lib/Constants.d.ts +1 -0
  46. package/dist/lib/Constants.js +5 -0
  47. package/dist/lib/Constants.js.map +1 -1
  48. package/dist/src/android/android-wizard.js +2 -4
  49. package/dist/src/android/android-wizard.js.map +1 -1
  50. package/dist/src/angular/angular-wizard.js +4 -6
  51. package/dist/src/angular/angular-wizard.js.map +1 -1
  52. package/dist/src/angular/sdk-setup.js +1 -1
  53. package/dist/src/angular/sdk-setup.js.map +1 -1
  54. package/dist/src/apple/apple-wizard.js +2 -4
  55. package/dist/src/apple/apple-wizard.js.map +1 -1
  56. package/dist/src/cloudflare/cloudflare-wizard.d.ts +3 -0
  57. package/dist/src/cloudflare/cloudflare-wizard.js +99 -0
  58. package/dist/src/cloudflare/cloudflare-wizard.js.map +1 -0
  59. package/dist/src/cloudflare/sdk-setup.d.ts +7 -0
  60. package/dist/src/cloudflare/sdk-setup.js +47 -0
  61. package/dist/src/cloudflare/sdk-setup.js.map +1 -0
  62. package/dist/src/cloudflare/templates.d.ts +4 -0
  63. package/dist/src/cloudflare/templates.js +44 -0
  64. package/dist/src/cloudflare/templates.js.map +1 -0
  65. package/dist/src/cloudflare/wrangler/create-wrangler-config.d.ts +4 -0
  66. package/dist/src/cloudflare/wrangler/create-wrangler-config.js +27 -0
  67. package/dist/src/cloudflare/wrangler/create-wrangler-config.js.map +1 -0
  68. package/dist/src/cloudflare/wrangler/ensure-wrangler-config.d.ts +4 -0
  69. package/dist/src/cloudflare/wrangler/ensure-wrangler-config.js +25 -0
  70. package/dist/src/cloudflare/wrangler/ensure-wrangler-config.js.map +1 -0
  71. package/dist/src/cloudflare/wrangler/find-wrangler-config.d.ts +4 -0
  72. package/dist/src/cloudflare/wrangler/find-wrangler-config.js +23 -0
  73. package/dist/src/cloudflare/wrangler/find-wrangler-config.js.map +1 -0
  74. package/dist/src/cloudflare/wrangler/get-entry-point-from-wrangler-config.d.ts +6 -0
  75. package/dist/src/cloudflare/wrangler/get-entry-point-from-wrangler-config.js +52 -0
  76. package/dist/src/cloudflare/wrangler/get-entry-point-from-wrangler-config.js.map +1 -0
  77. package/dist/src/cloudflare/wrangler/update-wrangler-config.d.ts +17 -0
  78. package/dist/src/cloudflare/wrangler/update-wrangler-config.js +173 -0
  79. package/dist/src/cloudflare/wrangler/update-wrangler-config.js.map +1 -0
  80. package/dist/src/cloudflare/wrap-worker.d.ts +32 -0
  81. package/dist/src/cloudflare/wrap-worker.js +109 -0
  82. package/dist/src/cloudflare/wrap-worker.js.map +1 -0
  83. package/dist/src/flutter/flutter-wizard.js +3 -6
  84. package/dist/src/flutter/flutter-wizard.js.map +1 -1
  85. package/dist/src/nextjs/nextjs-wizard.js +46 -10
  86. package/dist/src/nextjs/nextjs-wizard.js.map +1 -1
  87. package/dist/src/nextjs/templates.d.ts +6 -3
  88. package/dist/src/nextjs/templates.js +144 -93
  89. package/dist/src/nextjs/templates.js.map +1 -1
  90. package/dist/src/nuxt/nuxt-wizard.js +3 -5
  91. package/dist/src/nuxt/nuxt-wizard.js.map +1 -1
  92. package/dist/src/react-native/react-native-wizard.js +2 -4
  93. package/dist/src/react-native/react-native-wizard.js.map +1 -1
  94. package/dist/src/react-router/codemods/client.entry.js +4 -1
  95. package/dist/src/react-router/codemods/client.entry.js.map +1 -1
  96. package/dist/src/react-router/react-router-wizard.js +3 -5
  97. package/dist/src/react-router/react-router-wizard.js.map +1 -1
  98. package/dist/src/react-router/sdk-example.js +5 -2
  99. package/dist/src/react-router/sdk-example.js.map +1 -1
  100. package/dist/src/react-router/sdk-setup.d.ts +1 -1
  101. package/dist/src/react-router/sdk-setup.js +3 -4
  102. package/dist/src/react-router/sdk-setup.js.map +1 -1
  103. package/dist/src/remix/remix-wizard.js +2 -4
  104. package/dist/src/remix/remix-wizard.js.map +1 -1
  105. package/dist/src/run.d.ts +1 -1
  106. package/dist/src/run.js +5 -0
  107. package/dist/src/run.js.map +1 -1
  108. package/dist/src/sourcemaps/tools/sentry-cli.js +1 -1
  109. package/dist/src/sourcemaps/tools/sentry-cli.js.map +1 -1
  110. package/dist/src/sourcemaps/tools/wrangler.js +1 -1
  111. package/dist/src/sourcemaps/tools/wrangler.js.map +1 -1
  112. package/dist/src/sveltekit/sveltekit-wizard.js +4 -6
  113. package/dist/src/sveltekit/sveltekit-wizard.js.map +1 -1
  114. package/dist/src/telemetry.d.ts +1 -1
  115. package/dist/src/telemetry.js +52 -31
  116. package/dist/src/telemetry.js.map +1 -1
  117. package/dist/src/utils/abort-if-sportlight-not-supported.d.ts +5 -0
  118. package/dist/src/utils/abort-if-sportlight-not-supported.js +40 -0
  119. package/dist/src/utils/abort-if-sportlight-not-supported.js.map +1 -0
  120. package/dist/src/utils/ast-utils.d.ts +1 -1
  121. package/dist/src/utils/ast-utils.js.map +1 -1
  122. package/dist/src/utils/clack/index.d.ts +19 -2
  123. package/dist/src/utils/clack/index.js +174 -12
  124. package/dist/src/utils/clack/index.js.map +1 -1
  125. package/dist/src/utils/clack/mcp-config.js +117 -59
  126. package/dist/src/utils/clack/mcp-config.js.map +1 -1
  127. package/dist/src/version.d.ts +1 -1
  128. package/dist/src/version.js +1 -1
  129. package/dist/src/version.js.map +1 -1
  130. package/dist/test/angular/angular-wizard.test.js +2 -4
  131. package/dist/test/angular/angular-wizard.test.js.map +1 -1
  132. package/dist/test/apple/cocoapod.test.js +7 -3
  133. package/dist/test/apple/cocoapod.test.js.map +1 -1
  134. package/dist/test/apple/code-tools.test.js +8 -2
  135. package/dist/test/apple/code-tools.test.js.map +1 -1
  136. package/dist/test/cloudflare/create-wrangler-config.test.d.ts +1 -0
  137. package/dist/test/cloudflare/create-wrangler-config.test.js +48 -0
  138. package/dist/test/cloudflare/create-wrangler-config.test.js.map +1 -0
  139. package/dist/test/cloudflare/ensure-wrangler-config.test.d.ts +1 -0
  140. package/dist/test/cloudflare/ensure-wrangler-config.test.js +61 -0
  141. package/dist/test/cloudflare/ensure-wrangler-config.test.js.map +1 -0
  142. package/dist/test/cloudflare/find-wrangler-config.test.d.ts +1 -0
  143. package/dist/test/cloudflare/find-wrangler-config.test.js +77 -0
  144. package/dist/test/cloudflare/find-wrangler-config.test.js.map +1 -0
  145. package/dist/test/cloudflare/get-entry-point-from-wrangler-config.test.d.ts +1 -0
  146. package/dist/test/cloudflare/get-entry-point-from-wrangler-config.test.js +81 -0
  147. package/dist/test/cloudflare/get-entry-point-from-wrangler-config.test.js.map +1 -0
  148. package/dist/test/cloudflare/sdk-setup.test.d.ts +1 -0
  149. package/dist/test/cloudflare/sdk-setup.test.js +152 -0
  150. package/dist/test/cloudflare/sdk-setup.test.js.map +1 -0
  151. package/dist/test/cloudflare/templates.test.d.ts +1 -0
  152. package/dist/test/cloudflare/templates.test.js +68 -0
  153. package/dist/test/cloudflare/templates.test.js.map +1 -0
  154. package/dist/test/cloudflare/update-wrangler-config.test.d.ts +1 -0
  155. package/dist/test/cloudflare/update-wrangler-config.test.js +216 -0
  156. package/dist/test/cloudflare/update-wrangler-config.test.js.map +1 -0
  157. package/dist/test/cloudflare/wrap-worker.test.d.ts +1 -0
  158. package/dist/test/cloudflare/wrap-worker.test.js +143 -0
  159. package/dist/test/cloudflare/wrap-worker.test.js.map +1 -0
  160. package/dist/test/nextjs/templates.test.js +156 -87
  161. package/dist/test/nextjs/templates.test.js.map +1 -1
  162. package/dist/test/nextjs/wizard-double-wrap-prevention.test.js +12 -7
  163. package/dist/test/nextjs/wizard-double-wrap-prevention.test.js.map +1 -1
  164. package/dist/test/react-router/sdk-setup.test.js +2 -2
  165. package/dist/test/react-router/sdk-setup.test.js.map +1 -1
  166. package/dist/test/utils/clack/index.test.js +37 -29
  167. package/dist/test/utils/clack/index.test.js.map +1 -1
  168. package/dist/test/utils/clack/mcp-config.test.js +176 -51
  169. package/dist/test/utils/clack/mcp-config.test.js.map +1 -1
  170. package/package.json +6 -5
@@ -1,86 +1,56 @@
1
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
2
  Object.defineProperty(exports, "__esModule", { value: true });
26
- const path = __importStar(require("node:path"));
27
3
  const Constants_1 = require("../../lib/Constants");
28
4
  const utils_1 = require("../utils");
29
5
  const vitest_1 = require("vitest");
6
+ //@ts-expect-error - clifty is ESM only
7
+ const clifty_1 = require("clifty");
30
8
  (0, vitest_1.describe)('ReactNative', () => {
31
9
  const integration = Constants_1.Integration.reactNative;
32
- const projectDir = path.resolve(__dirname, '../test-applications/react-native-test-app');
33
- let podInstallPrompted = false;
10
+ let wizardExitCode;
11
+ const { projectDir, cleanup } = (0, utils_1.createIsolatedTestEnv)('react-native-test-app');
34
12
  (0, vitest_1.beforeAll)(async () => {
35
- const wizardInstance = (0, utils_1.startWizardInstance)(integration, projectDir);
36
- const packageManagerPrompted = await wizardInstance.waitForOutput('Please select your package manager.');
37
- const sessionReplayPrompted = packageManagerPrompted &&
38
- (await wizardInstance.sendStdinAndWaitForOutput(
39
- // Selecting `yarn` as the package manager
40
- [utils_1.KEYS.DOWN, utils_1.KEYS.DOWN, utils_1.KEYS.ENTER], 'Do you want to enable Session Replay to help debug issues? (See https://docs.sentry.io/platforms/react-native/session-replay/)'),
41
- {
42
- timeout: 240000,
43
- });
44
- const feedbackWidgetPrompted = sessionReplayPrompted &&
45
- (await wizardInstance.sendStdinAndWaitForOutput(
46
- // Enable session replay
47
- [utils_1.KEYS.ENTER], 'Do you want to enable the Feedback Widget to collect feedback from your users? (See https://docs.sentry.io/platforms/react-native/user-feedback/)'));
48
- const logsPrompted = feedbackWidgetPrompted &&
49
- (await wizardInstance.sendStdinAndWaitForOutput(
50
- // Enable feedback widget
51
- [utils_1.KEYS.ENTER], 'Do you want to enable Logs? (See https://docs.sentry.io/platforms/react-native/logs/)'));
52
- podInstallPrompted =
53
- logsPrompted &&
54
- (await wizardInstance.sendStdinAndWaitForOutput(
55
- // Enable logs
56
- [utils_1.KEYS.ENTER], 'Do you want to run `pod install` now?', {
57
- optional: true,
58
- timeout: 5000,
59
- }));
60
- const prettierPrompted = podInstallPrompted &&
61
- (await wizardInstance.sendStdinAndWaitForOutput(
62
- // Skip pod install
63
- [utils_1.KEYS.DOWN, utils_1.KEYS.ENTER], 'Looks like you have Prettier in your project. Do you want to run it on your files?'));
64
- // Handle the MCP prompt (default is now Yes, so press DOWN to select No)
65
- const mcpPrompted = prettierPrompted &&
66
- (await wizardInstance.sendStdinAndWaitForOutput(
67
- // Skip prettier
68
- [utils_1.KEYS.DOWN, utils_1.KEYS.ENTER], 'Optionally add a project-scoped MCP server configuration for the Sentry MCP?', {
69
- optional: true,
70
- }));
71
- const testEventPrompted = mcpPrompted &&
72
- (await wizardInstance.sendStdinAndWaitForOutput(
73
- // Decline MCP config by selecting No
74
- [utils_1.KEYS.DOWN, utils_1.KEYS.ENTER], 'Have you successfully sent a test event?'));
75
- testEventPrompted &&
76
- (await wizardInstance.sendStdinAndWaitForOutput(
77
- // Respond that test event was sent
78
- [utils_1.KEYS.ENTER], 'Everything is set up!'));
79
- wizardInstance.kill();
13
+ const wizardInteraction = (0, clifty_1.withEnv)({
14
+ cwd: projectDir,
15
+ debug: true,
16
+ })
17
+ .defineInteraction()
18
+ .whenAsked('Please select your package manager.')
19
+ .respondWith(clifty_1.KEYS.DOWN, clifty_1.KEYS.ENTER)
20
+ .expectOutput('Installing @sentry/react-native')
21
+ .expectOutput('Installed @sentry/react-native', {
22
+ timeout: 240000,
23
+ })
24
+ .whenAsked('Do you want to enable Session Replay')
25
+ .respondWith(clifty_1.KEYS.ENTER)
26
+ .whenAsked('Do you want to enable the Feedback Widget to collect feedback from your users?')
27
+ .respondWith(clifty_1.KEYS.ENTER)
28
+ .whenAsked('Do you want to enable Logs')
29
+ .respondWith(clifty_1.KEYS.ENTER);
30
+ // Only prompt to run `pod install` if running on macOS.
31
+ if (process.platform === 'darwin') {
32
+ wizardInteraction
33
+ .whenAsked('Do you want to run `pod install` now?')
34
+ .respondWith(clifty_1.KEYS.ENTER)
35
+ .expectOutput('Pods installed.', { timeout: 240000 });
36
+ }
37
+ wizardExitCode = await wizardInteraction
38
+ .expectOutput('Added Sentry.init to App.tsx')
39
+ .whenAsked('Looks like you have Prettier in your project. Do you want to run it on your files?')
40
+ .respondWith(clifty_1.KEYS.DOWN, clifty_1.KEYS.ENTER)
41
+ .whenAsked('Optionally add a project-scoped MCP server configuration for the Sentry MCP?')
42
+ .respondWith(clifty_1.KEYS.DOWN, clifty_1.KEYS.ENTER)
43
+ .expectOutput('To make sure everything is set up correctly, put the following code snippet into your application.')
44
+ .whenAsked('Have you successfully sent a test event?')
45
+ .respondWith(clifty_1.KEYS.ENTER)
46
+ .expectOutput('Everything is set up!')
47
+ .run((0, utils_1.getWizardCommand)(integration));
80
48
  });
81
49
  (0, vitest_1.afterAll)(() => {
82
- (0, utils_1.revertLocalChanges)(projectDir);
83
- (0, utils_1.cleanupGit)(projectDir);
50
+ cleanup();
51
+ });
52
+ (0, vitest_1.test)('exits with exit code 0', () => {
53
+ (0, vitest_1.expect)(wizardExitCode).toBe(0);
84
54
  });
85
55
  (0, vitest_1.test)('package.json is updated correctly', () => {
86
56
  (0, utils_1.checkFileContents)(`${projectDir}/package.json`, `@sentry/react-native`);
@@ -115,9 +85,6 @@ Sentry.init({
115
85
  (0, utils_1.checkFileContents)(`${projectDir}/App.tsx`, `export default Sentry.wrap(App);`);
116
86
  });
117
87
  (0, vitest_1.test)('ios/sentry.properties is added', () => {
118
- if (!podInstallPrompted) {
119
- return;
120
- }
121
88
  (0, utils_1.checkFileContents)(`${projectDir}/ios/sentry.properties`, `auth.token=${utils_1.TEST_ARGS.AUTH_TOKEN}
122
89
 
123
90
  defaults.org=${utils_1.TEST_ARGS.ORG_SLUG}
@@ -136,10 +103,7 @@ defaults.url=https://sentry.io/`);
136
103
  (0, vitest_1.test)('build.gradle is updated correctly', () => {
137
104
  (0, utils_1.checkFileContents)(`${projectDir}/android/app/build.gradle`, `apply from: new File(["node", "--print", "require.resolve('@sentry/react-native/package.json')"].execute().text.trim(), "../sentry.gradle")`);
138
105
  });
139
- (0, vitest_1.test)('xcode project is updated correctly', () => {
140
- if (!podInstallPrompted) {
141
- return;
142
- }
106
+ vitest_1.test.skipIf(process.platform !== 'darwin')('xcode project is updated correctly', () => {
143
107
  (0, utils_1.checkFileContents)(`${projectDir}/ios/reactnative078.xcodeproj/project.pbxproj`, `@sentry/react-native/scripts/sentry-xcode.sh`);
144
108
  (0, utils_1.checkFileContents)(`${projectDir}/ios/reactnative078.xcodeproj/project.pbxproj`, `../node_modules/@sentry/react-native/scripts/sentry-xcode-debug-files.sh`);
145
109
  });
@@ -1 +1 @@
1
- {"version":3,"file":"react-native.test.js","sourceRoot":"","sources":["../../../e2e-tests/tests/react-native.test.ts"],"names":[],"mappings":"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","sourcesContent":["import * as path from 'node:path';\nimport { Integration } from '../../lib/Constants';\nimport {\n KEYS,\n TEST_ARGS,\n cleanupGit,\n checkFileContents,\n checkIfReactNativeBundles,\n revertLocalChanges,\n startWizardInstance,\n} from '../utils';\nimport { afterAll, beforeAll, describe, test, expect } from 'vitest';\n\ndescribe('ReactNative', () => {\n const integration = Integration.reactNative;\n const projectDir = path.resolve(\n __dirname,\n '../test-applications/react-native-test-app',\n );\n\n let podInstallPrompted = false;\n\n beforeAll(async () => {\n const wizardInstance = startWizardInstance(integration, projectDir);\n const packageManagerPrompted = await wizardInstance.waitForOutput(\n 'Please select your package manager.',\n );\n const sessionReplayPrompted =\n packageManagerPrompted &&\n (await wizardInstance.sendStdinAndWaitForOutput(\n // Selecting `yarn` as the package manager\n [KEYS.DOWN, KEYS.DOWN, KEYS.ENTER],\n 'Do you want to enable Session Replay to help debug issues? (See https://docs.sentry.io/platforms/react-native/session-replay/)',\n ),\n {\n timeout: 240_000,\n });\n\n const feedbackWidgetPrompted =\n sessionReplayPrompted &&\n (await wizardInstance.sendStdinAndWaitForOutput(\n // Enable session replay\n [KEYS.ENTER],\n 'Do you want to enable the Feedback Widget to collect feedback from your users? (See https://docs.sentry.io/platforms/react-native/user-feedback/)',\n ));\n\n const logsPrompted =\n feedbackWidgetPrompted &&\n (await wizardInstance.sendStdinAndWaitForOutput(\n // Enable feedback widget\n [KEYS.ENTER],\n 'Do you want to enable Logs? (See https://docs.sentry.io/platforms/react-native/logs/)',\n ));\n\n podInstallPrompted =\n logsPrompted &&\n (await wizardInstance.sendStdinAndWaitForOutput(\n // Enable logs\n [KEYS.ENTER],\n 'Do you want to run `pod install` now?',\n {\n optional: true,\n timeout: 5000,\n },\n ));\n\n const prettierPrompted =\n podInstallPrompted &&\n (await wizardInstance.sendStdinAndWaitForOutput(\n // Skip pod install\n [KEYS.DOWN, KEYS.ENTER],\n 'Looks like you have Prettier in your project. Do you want to run it on your files?',\n ));\n\n // Handle the MCP prompt (default is now Yes, so press DOWN to select No)\n const mcpPrompted =\n prettierPrompted &&\n (await wizardInstance.sendStdinAndWaitForOutput(\n // Skip prettier\n [KEYS.DOWN, KEYS.ENTER],\n 'Optionally add a project-scoped MCP server configuration for the Sentry MCP?',\n {\n optional: true,\n },\n ));\n\n const testEventPrompted =\n mcpPrompted &&\n (await wizardInstance.sendStdinAndWaitForOutput(\n // Decline MCP config by selecting No\n [KEYS.DOWN, KEYS.ENTER],\n 'Have you successfully sent a test event?',\n ));\n\n testEventPrompted &&\n (await wizardInstance.sendStdinAndWaitForOutput(\n // Respond that test event was sent\n [KEYS.ENTER],\n 'Everything is set up!',\n ));\n wizardInstance.kill();\n });\n\n afterAll(() => {\n revertLocalChanges(projectDir);\n cleanupGit(projectDir);\n });\n\n test('package.json is updated correctly', () => {\n checkFileContents(`${projectDir}/package.json`, `@sentry/react-native`);\n });\n\n test('metro.config.js is updated correctly', () => {\n checkFileContents(\n `${projectDir}/metro.config.js`,\n `const {\n withSentryConfig\n} = require(\"@sentry/react-native/metro\");`,\n );\n checkFileContents(\n `${projectDir}/metro.config.js`,\n `module.exports = withSentryConfig(mergeConfig(getDefaultConfig(__dirname), config));`,\n );\n });\n\n test('App.tsx is updated correctly', () => {\n checkFileContents(\n `${projectDir}/App.tsx`,\n `import * as Sentry from '@sentry/react-native';\n\nSentry.init({\n dsn: 'https://public@dsn.ingest.sentry.io/1337',\n\n // Adds more context data to events (IP address, cookies, user, etc.)\n // For more information, visit: https://docs.sentry.io/platforms/react-native/data-management/data-collected/\n sendDefaultPii: true,\n\n // Enable Logs\n enableLogs: true,\n\n // Configure Session Replay\n replaysSessionSampleRate: 0.1,\n replaysOnErrorSampleRate: 1,\n integrations: [Sentry.mobileReplayIntegration(), Sentry.feedbackIntegration()],\n\n // uncomment the line below to enable Spotlight (https://spotlightjs.com)\n // spotlight: __DEV__,\n});`,\n );\n checkFileContents(\n `${projectDir}/App.tsx`,\n `export default Sentry.wrap(App);`,\n );\n });\n\n test('ios/sentry.properties is added', () => {\n if (!podInstallPrompted) {\n return;\n }\n checkFileContents(\n `${projectDir}/ios/sentry.properties`,\n `auth.token=${TEST_ARGS.AUTH_TOKEN}\n\ndefaults.org=${TEST_ARGS.ORG_SLUG}\ndefaults.project=${TEST_ARGS.PROJECT_SLUG}\n\ndefaults.url=https://sentry.io/`,\n );\n });\n\n test('android/sentry.properties is added', () => {\n checkFileContents(\n `${projectDir}/android/sentry.properties`,\n `auth.token=${TEST_ARGS.AUTH_TOKEN}\n\ndefaults.org=${TEST_ARGS.ORG_SLUG}\ndefaults.project=${TEST_ARGS.PROJECT_SLUG}\n\ndefaults.url=https://sentry.io/`,\n );\n });\n\n test('build.gradle is updated correctly', () => {\n checkFileContents(\n `${projectDir}/android/app/build.gradle`,\n `apply from: new File([\"node\", \"--print\", \"require.resolve('@sentry/react-native/package.json')\"].execute().text.trim(), \"../sentry.gradle\")`,\n );\n });\n\n test('xcode project is updated correctly', () => {\n if (!podInstallPrompted) {\n return;\n }\n checkFileContents(\n `${projectDir}/ios/reactnative078.xcodeproj/project.pbxproj`,\n `@sentry/react-native/scripts/sentry-xcode.sh`,\n );\n checkFileContents(\n `${projectDir}/ios/reactnative078.xcodeproj/project.pbxproj`,\n `../node_modules/@sentry/react-native/scripts/sentry-xcode-debug-files.sh`,\n );\n });\n\n test('android project is bundled correctly', async () => {\n const bundled = await checkIfReactNativeBundles(projectDir, 'android');\n expect(bundled).toBe(true);\n });\n\n test('ios project is bundled correctly', async () => {\n const bundled = await checkIfReactNativeBundles(projectDir, 'ios');\n expect(bundled).toBe(true);\n });\n});\n"]}
1
+ {"version":3,"file":"react-native.test.js","sourceRoot":"","sources":["../../../e2e-tests/tests/react-native.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { Integration } from '../../lib/Constants';\nimport {\n TEST_ARGS,\n checkFileContents,\n checkIfReactNativeBundles,\n createIsolatedTestEnv,\n getWizardCommand,\n} from '../utils';\nimport { afterAll, beforeAll, describe, test, expect } from 'vitest';\n\n//@ts-expect-error - clifty is ESM only\nimport { KEYS, withEnv } from 'clifty';\n\ndescribe('ReactNative', () => {\n const integration = Integration.reactNative;\n let wizardExitCode: number;\n const { projectDir, cleanup } = createIsolatedTestEnv(\n 'react-native-test-app',\n );\n\n beforeAll(async () => {\n const wizardInteraction = withEnv({\n cwd: projectDir,\n debug: true,\n })\n .defineInteraction()\n\n .whenAsked('Please select your package manager.')\n .respondWith(KEYS.DOWN, KEYS.ENTER)\n .expectOutput('Installing @sentry/react-native')\n .expectOutput('Installed @sentry/react-native', {\n timeout: 240_000,\n })\n .whenAsked('Do you want to enable Session Replay')\n .respondWith(KEYS.ENTER)\n .whenAsked(\n 'Do you want to enable the Feedback Widget to collect feedback from your users?',\n )\n .respondWith(KEYS.ENTER)\n .whenAsked('Do you want to enable Logs')\n .respondWith(KEYS.ENTER);\n\n // Only prompt to run `pod install` if running on macOS.\n if (process.platform === 'darwin') {\n wizardInteraction\n .whenAsked('Do you want to run `pod install` now?')\n .respondWith(KEYS.ENTER)\n .expectOutput('Pods installed.', { timeout: 240_000 });\n }\n\n wizardExitCode = await wizardInteraction\n .expectOutput('Added Sentry.init to App.tsx')\n .whenAsked(\n 'Looks like you have Prettier in your project. Do you want to run it on your files?',\n )\n .respondWith(KEYS.DOWN, 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(\n 'To make sure everything is set up correctly, put the following code snippet into your application.',\n )\n .whenAsked('Have you successfully sent a test event?')\n .respondWith(KEYS.ENTER)\n .expectOutput('Everything is set up!')\n .run(getWizardCommand(integration));\n });\n\n afterAll(() => {\n cleanup();\n });\n\n test('exits with exit code 0', () => {\n expect(wizardExitCode).toBe(0);\n });\n\n test('package.json is updated correctly', () => {\n checkFileContents(`${projectDir}/package.json`, `@sentry/react-native`);\n });\n\n test('metro.config.js is updated correctly', () => {\n checkFileContents(\n `${projectDir}/metro.config.js`,\n `const {\n withSentryConfig\n} = require(\"@sentry/react-native/metro\");`,\n );\n checkFileContents(\n `${projectDir}/metro.config.js`,\n `module.exports = withSentryConfig(mergeConfig(getDefaultConfig(__dirname), config));`,\n );\n });\n\n test('App.tsx is updated correctly', () => {\n checkFileContents(\n `${projectDir}/App.tsx`,\n `import * as Sentry from '@sentry/react-native';\n\nSentry.init({\n dsn: 'https://public@dsn.ingest.sentry.io/1337',\n\n // Adds more context data to events (IP address, cookies, user, etc.)\n // For more information, visit: https://docs.sentry.io/platforms/react-native/data-management/data-collected/\n sendDefaultPii: true,\n\n // Enable Logs\n enableLogs: true,\n\n // Configure Session Replay\n replaysSessionSampleRate: 0.1,\n replaysOnErrorSampleRate: 1,\n integrations: [Sentry.mobileReplayIntegration(), Sentry.feedbackIntegration()],\n\n // uncomment the line below to enable Spotlight (https://spotlightjs.com)\n // spotlight: __DEV__,\n});`,\n );\n checkFileContents(\n `${projectDir}/App.tsx`,\n `export default Sentry.wrap(App);`,\n );\n });\n\n test('ios/sentry.properties is added', () => {\n checkFileContents(\n `${projectDir}/ios/sentry.properties`,\n `auth.token=${TEST_ARGS.AUTH_TOKEN}\n\ndefaults.org=${TEST_ARGS.ORG_SLUG}\ndefaults.project=${TEST_ARGS.PROJECT_SLUG}\n\ndefaults.url=https://sentry.io/`,\n );\n });\n\n test('android/sentry.properties is added', () => {\n checkFileContents(\n `${projectDir}/android/sentry.properties`,\n `auth.token=${TEST_ARGS.AUTH_TOKEN}\n\ndefaults.org=${TEST_ARGS.ORG_SLUG}\ndefaults.project=${TEST_ARGS.PROJECT_SLUG}\n\ndefaults.url=https://sentry.io/`,\n );\n });\n\n test('build.gradle is updated correctly', () => {\n checkFileContents(\n `${projectDir}/android/app/build.gradle`,\n `apply from: new File([\"node\", \"--print\", \"require.resolve('@sentry/react-native/package.json')\"].execute().text.trim(), \"../sentry.gradle\")`,\n );\n });\n\n test.skipIf(process.platform !== 'darwin')(\n 'xcode project is updated correctly',\n () => {\n checkFileContents(\n `${projectDir}/ios/reactnative078.xcodeproj/project.pbxproj`,\n `@sentry/react-native/scripts/sentry-xcode.sh`,\n );\n checkFileContents(\n `${projectDir}/ios/reactnative078.xcodeproj/project.pbxproj`,\n `../node_modules/@sentry/react-native/scripts/sentry-xcode-debug-files.sh`,\n );\n },\n );\n\n test('android project is bundled correctly', async () => {\n const bundled = await checkIfReactNativeBundles(projectDir, 'android');\n expect(bundled).toBe(true);\n });\n\n test('ios project is bundled correctly', async () => {\n const bundled = await checkIfReactNativeBundles(projectDir, 'ios');\n expect(bundled).toBe(true);\n });\n});\n"]}
@@ -28,136 +28,160 @@ const fs = __importStar(require("node:fs"));
28
28
  const Constants_1 = require("../../lib/Constants");
29
29
  const utils_1 = require("../utils");
30
30
  const vitest_1 = require("vitest");
31
- async function runWizardOnReactRouterProject(projectDir, integration) {
32
- const wizardInstance = (0, utils_1.startWizardInstance)(integration, projectDir);
33
- const packageManagerPrompted = await wizardInstance.waitForOutput('Please select your package manager.');
34
- const tracingOptionPrompted = packageManagerPrompted &&
35
- (await wizardInstance.sendStdinAndWaitForOutput([utils_1.KEYS.DOWN, utils_1.KEYS.ENTER], 'to track the performance of your application?', { timeout: 240000 }));
36
- const replayOptionPrompted = tracingOptionPrompted &&
37
- (await wizardInstance.sendStdinAndWaitForOutput([utils_1.KEYS.ENTER], 'to get a video-like reproduction of errors during a user session?'));
38
- const logOptionPrompted = replayOptionPrompted &&
39
- (await wizardInstance.sendStdinAndWaitForOutput([utils_1.KEYS.ENTER], 'to send your application logs to Sentry?'));
40
- const profilingOptionPrompted = logOptionPrompted &&
41
- (await wizardInstance.sendStdinAndWaitForOutput([utils_1.KEYS.ENTER], 'to track application performance in detail?'));
42
- const examplePagePrompted = profilingOptionPrompted &&
43
- (await wizardInstance.sendStdinAndWaitForOutput([utils_1.KEYS.ENTER], 'Do you want to create an example page'));
44
- const mcpPrompted = examplePagePrompted &&
45
- (await wizardInstance.sendStdinAndWaitForOutput([utils_1.KEYS.ENTER], 'Optionally add a project-scoped MCP server configuration for the Sentry MCP?', { optional: true }));
46
- mcpPrompted &&
47
- (await wizardInstance.sendStdinAndWaitForOutput([utils_1.KEYS.DOWN, utils_1.KEYS.ENTER], 'Successfully installed the Sentry React Router SDK!'));
48
- wizardInstance.kill();
49
- }
50
- function checkReactRouterProject(projectDir, integration) {
51
- (0, vitest_1.test)('package.json is updated correctly', () => {
52
- (0, utils_1.checkPackageJson)(projectDir, integration);
53
- });
54
- (0, vitest_1.test)('.env.sentry-build-plugin is created and contains the auth token', () => {
55
- (0, utils_1.checkEnvBuildPlugin)(projectDir);
56
- });
57
- (0, vitest_1.test)('example page exists', () => {
58
- (0, utils_1.checkFileExists)(`${projectDir}/app/routes/sentry-example-page.tsx`);
59
- });
60
- (0, vitest_1.test)('example API route exists', () => {
61
- (0, utils_1.checkFileExists)(`${projectDir}/app/routes/api.sentry-example-api.ts`);
62
- });
63
- (0, vitest_1.test)('example page is added to routes configuration', () => {
64
- (0, utils_1.checkFileContents)(`${projectDir}/app/routes.ts`, [
65
- 'route("/sentry-example-page", "routes/sentry-example-page.tsx")',
66
- 'route("/api/sentry-example-api", "routes/api.sentry-example-api.ts")',
67
- ]);
68
- });
69
- (0, vitest_1.test)('instrument.server file exists', () => {
70
- (0, utils_1.checkFileExists)(`${projectDir}/instrument.server.mjs`);
71
- });
72
- (0, vitest_1.test)('entry.client file contains Sentry initialization', () => {
73
- (0, utils_1.checkFileContents)(`${projectDir}/app/entry.client.tsx`, [
74
- 'import * as Sentry from',
75
- '@sentry/react-router',
76
- `Sentry.init({
77
- dsn: "${utils_1.TEST_ARGS.PROJECT_DSN}",`,
78
- 'integrations: [Sentry.reactRouterTracingIntegration(), Sentry.replayIntegration()]',
79
- 'enableLogs: true,',
80
- 'tracesSampleRate: 1.0,',
81
- ]);
82
- });
83
- (0, vitest_1.test)('package.json scripts are updated correctly', () => {
84
- (0, utils_1.checkFileContents)(`${projectDir}/package.json`, [
85
- `"start": "NODE_OPTIONS='--import ./instrument.server.mjs' react-router-serve ./build/server/index.js"`,
86
- `"dev": "NODE_OPTIONS='--import ./instrument.server.mjs' react-router dev"`,
87
- ]);
88
- });
89
- (0, vitest_1.test)('entry.server file contains Sentry instrumentation', () => {
90
- (0, utils_1.checkFileContents)(`${projectDir}/app/entry.server.tsx`, [
91
- 'import * as Sentry from',
92
- '@sentry/react-router',
93
- 'export const handleError = Sentry.createSentryHandleError(',
94
- 'export default Sentry.wrapSentryHandleRequest(handleRequest);'
95
- ]);
96
- });
97
- (0, vitest_1.test)('instrument.server file contains Sentry initialization', () => {
98
- (0, utils_1.checkFileContents)(`${projectDir}/instrument.server.mjs`, [
99
- 'import * as Sentry from \'@sentry/react-router\';',
100
- `Sentry.init({
101
- dsn: "${utils_1.TEST_ARGS.PROJECT_DSN}",`,
102
- 'enableLogs: true,',
103
- ]);
104
- });
105
- (0, vitest_1.test)('root file contains Sentry ErrorBoundary', () => {
106
- (0, utils_1.checkFileContents)(`${projectDir}/app/root.tsx`, [
107
- 'import * as Sentry from',
108
- '@sentry/react-router',
109
- 'export function ErrorBoundary',
110
- 'Sentry.captureException(error)',
111
- ]);
112
- });
113
- (0, vitest_1.test)('vite.config file contains sentryReactRouter plugin', () => {
114
- (0, utils_1.checkFileContents)(`${projectDir}/vite.config.ts`, [
115
- 'import { sentryReactRouter } from',
116
- '@sentry/react-router',
117
- 'sentryReactRouter(',
118
- 'authToken: process.env.SENTRY_AUTH_TOKEN',
119
- ]);
120
- });
121
- (0, vitest_1.test)('react-router.config file contains buildEnd hook with sentryOnBuildEnd', () => {
122
- (0, utils_1.checkFileContents)(`${projectDir}/react-router.config.ts`, [
123
- 'import { sentryOnBuildEnd } from',
124
- '@sentry/react-router',
125
- 'ssr: true,',
126
- 'buildEnd: async',
127
- 'await sentryOnBuildEnd({',
128
- ]);
129
- });
130
- (0, vitest_1.test)('builds successfully', async () => {
131
- await (0, utils_1.checkIfBuilds)(projectDir);
132
- }, 60000); // 1 minute timeout
133
- (0, vitest_1.test)('runs on dev mode correctly', async () => {
134
- await (0, utils_1.checkIfRunsOnDevMode)(projectDir, 'to expose');
135
- }, 30000); // 30 second timeout
136
- (0, vitest_1.test)('runs on prod mode correctly', async () => {
137
- await (0, utils_1.checkIfRunsOnProdMode)(projectDir, 'react-router-serve');
138
- }, 30000); // 30 second timeout
31
+ //@ts-expect-error - clifty is ESM only
32
+ const clifty_1 = require("clifty");
33
+ async function runWizardOnReactRouterProject(projectDir, opts) {
34
+ const { modifiedFiles = false } = opts || {};
35
+ const wizardInteraction = (0, clifty_1.withEnv)({
36
+ cwd: projectDir,
37
+ }).defineInteraction();
38
+ if (modifiedFiles) {
39
+ wizardInteraction
40
+ .whenAsked('Do you want to continue anyway?')
41
+ .respondWith(clifty_1.KEYS.ENTER);
42
+ }
43
+ wizardInteraction
44
+ .whenAsked('Please select your package manager.')
45
+ .respondWith(clifty_1.KEYS.DOWN, clifty_1.KEYS.ENTER)
46
+ .expectOutput('Installing @sentry/react-router')
47
+ .expectOutput('Installed @sentry/react-router', {
48
+ timeout: 240000,
49
+ })
50
+ .whenAsked('Do you want to enable Tracing')
51
+ .respondWith(clifty_1.KEYS.ENTER)
52
+ .whenAsked('Do you want to enable Session Replay')
53
+ .respondWith(clifty_1.KEYS.ENTER)
54
+ .whenAsked('Do you want to enable Logs')
55
+ .respondWith(clifty_1.KEYS.ENTER)
56
+ .whenAsked('Do you want to enable Profiling')
57
+ .respondWith(clifty_1.KEYS.ENTER)
58
+ .expectOutput('Installing @sentry/profiling-node')
59
+ .expectOutput('Installed @sentry/profiling-node', {
60
+ timeout: 240000,
61
+ })
62
+ .whenAsked('Do you want to create an example page')
63
+ .respondWith(clifty_1.KEYS.ENTER);
64
+ if (modifiedFiles) {
65
+ wizardInteraction
66
+ .whenAsked('Would you like to try running npx react-router reveal')
67
+ .respondWith(clifty_1.KEYS.ENTER)
68
+ .whenAsked('Did you apply the snippet above?')
69
+ .respondWith(clifty_1.KEYS.ENTER);
70
+ }
71
+ return wizardInteraction
72
+ .whenAsked('Optionally add a project-scoped MCP server configuration for the Sentry MCP?')
73
+ .respondWith(clifty_1.KEYS.DOWN, clifty_1.KEYS.ENTER)
74
+ .expectOutput('Successfully installed the Sentry React Router SDK!')
75
+ .run((0, utils_1.getWizardCommand)(Constants_1.Integration.reactRouter));
139
76
  }
140
77
  (0, vitest_1.describe)('React Router', () => {
141
78
  (0, vitest_1.describe)('with empty project', () => {
142
- const integration = Constants_1.Integration.reactRouter;
143
- const projectDir = path.resolve(__dirname, '../test-applications/react-router-test-app');
79
+ let wizardExitCode;
80
+ const { projectDir, cleanup } = (0, utils_1.createIsolatedTestEnv)('react-router-test-app');
144
81
  (0, vitest_1.beforeAll)(async () => {
145
- await runWizardOnReactRouterProject(projectDir, integration);
82
+ wizardExitCode = await runWizardOnReactRouterProject(projectDir);
146
83
  });
147
84
  (0, vitest_1.afterAll)(() => {
148
- (0, utils_1.revertLocalChanges)(projectDir);
149
- (0, utils_1.cleanupGit)(projectDir);
85
+ cleanup();
150
86
  });
151
- checkReactRouterProject(projectDir, integration);
87
+ (0, vitest_1.test)('exits with exit code 0', () => {
88
+ (0, vitest_1.expect)(wizardExitCode).toBe(0);
89
+ });
90
+ (0, vitest_1.test)('package.json is updated correctly', () => {
91
+ (0, utils_1.checkPackageJson)(projectDir, '@sentry/react-router');
92
+ });
93
+ (0, vitest_1.test)('.env.sentry-build-plugin is created and contains the auth token', () => {
94
+ (0, utils_1.checkEnvBuildPlugin)(projectDir);
95
+ });
96
+ (0, vitest_1.test)('example page exists', () => {
97
+ (0, utils_1.checkFileExists)(`${projectDir}/app/routes/sentry-example-page.tsx`);
98
+ });
99
+ (0, vitest_1.test)('example API route exists', () => {
100
+ (0, utils_1.checkFileExists)(`${projectDir}/app/routes/api.sentry-example-api.ts`);
101
+ });
102
+ (0, vitest_1.test)('example page is added to routes configuration', () => {
103
+ (0, utils_1.checkFileContents)(`${projectDir}/app/routes.ts`, [
104
+ 'route("/sentry-example-page", "routes/sentry-example-page.tsx")',
105
+ 'route("/api/sentry-example-api", "routes/api.sentry-example-api.ts")',
106
+ ]);
107
+ });
108
+ (0, vitest_1.test)('instrument.server file exists', () => {
109
+ (0, utils_1.checkFileExists)(`${projectDir}/instrument.server.mjs`);
110
+ });
111
+ (0, vitest_1.test)('entry.client file contains Sentry initialization', () => {
112
+ (0, utils_1.checkFileContents)(`${projectDir}/app/entry.client.tsx`, [
113
+ 'import * as Sentry from',
114
+ '@sentry/react-router',
115
+ `Sentry.init({
116
+ dsn: "${utils_1.TEST_ARGS.PROJECT_DSN}",`,
117
+ 'integrations: [Sentry.reactRouterTracingIntegration(), Sentry.replayIntegration()]',
118
+ 'enableLogs: true,',
119
+ 'tracesSampleRate: 1.0,',
120
+ ]);
121
+ });
122
+ (0, vitest_1.test)('package.json scripts are updated correctly', () => {
123
+ (0, utils_1.checkFileContents)(`${projectDir}/package.json`, [
124
+ `"start": "NODE_OPTIONS='--import ./instrument.server.mjs' react-router-serve ./build/server/index.js"`,
125
+ `"dev": "NODE_OPTIONS='--import ./instrument.server.mjs' react-router dev"`,
126
+ ]);
127
+ });
128
+ (0, vitest_1.test)('entry.server file contains Sentry instrumentation', () => {
129
+ (0, utils_1.checkFileContents)(`${projectDir}/app/entry.server.tsx`, [
130
+ 'import * as Sentry from',
131
+ '@sentry/react-router',
132
+ 'export const handleError = Sentry.createSentryHandleError(',
133
+ 'export default Sentry.wrapSentryHandleRequest(handleRequest);',
134
+ ]);
135
+ });
136
+ (0, vitest_1.test)('instrument.server file contains Sentry initialization', () => {
137
+ (0, utils_1.checkFileContents)(`${projectDir}/instrument.server.mjs`, [
138
+ "import * as Sentry from '@sentry/react-router';",
139
+ `Sentry.init({
140
+ dsn: "${utils_1.TEST_ARGS.PROJECT_DSN}",`,
141
+ 'enableLogs: true,',
142
+ ]);
143
+ });
144
+ (0, vitest_1.test)('root file contains Sentry ErrorBoundary', () => {
145
+ (0, utils_1.checkFileContents)(`${projectDir}/app/root.tsx`, [
146
+ 'import * as Sentry from',
147
+ '@sentry/react-router',
148
+ 'export function ErrorBoundary',
149
+ 'Sentry.captureException(error)',
150
+ ]);
151
+ });
152
+ (0, vitest_1.test)('vite.config file contains sentryReactRouter plugin', () => {
153
+ (0, utils_1.checkFileContents)(`${projectDir}/vite.config.ts`, [
154
+ 'import { sentryReactRouter } from',
155
+ '@sentry/react-router',
156
+ 'sentryReactRouter(',
157
+ 'authToken: process.env.SENTRY_AUTH_TOKEN',
158
+ ]);
159
+ });
160
+ (0, vitest_1.test)('react-router.config file contains buildEnd hook with sentryOnBuildEnd', () => {
161
+ (0, utils_1.checkFileContents)(`${projectDir}/react-router.config.ts`, [
162
+ 'import { sentryOnBuildEnd } from',
163
+ '@sentry/react-router',
164
+ 'ssr: true,',
165
+ 'buildEnd: async',
166
+ 'await sentryOnBuildEnd({',
167
+ ]);
168
+ });
169
+ (0, vitest_1.test)('builds successfully', async () => {
170
+ await (0, utils_1.checkIfBuilds)(projectDir);
171
+ }, 60000); // 1 minute timeout
172
+ (0, vitest_1.test)('runs on dev mode correctly', async () => {
173
+ await (0, utils_1.checkIfRunsOnDevMode)(projectDir, 'to expose');
174
+ }, 30000); // 30 second timeout
175
+ (0, vitest_1.test)('runs on prod mode correctly', async () => {
176
+ await (0, utils_1.checkIfRunsOnProdMode)(projectDir, 'react-router-serve');
177
+ }, 30000); // 30 second timeout
152
178
  });
153
179
  (0, vitest_1.describe)('edge cases', () => {
154
- const baseProjectDir = path.resolve(__dirname, '../test-applications/react-router-test-app');
155
180
  (0, vitest_1.describe)('existing Sentry setup', () => {
156
- const integration = Constants_1.Integration.reactRouter;
157
- const projectDir = path.resolve(__dirname, '../test-applications/react-router-test-app-existing');
181
+ let wizardExitCode;
182
+ const { projectDir, cleanup } = (0, utils_1.createIsolatedTestEnv)('react-router-test-app');
158
183
  (0, vitest_1.beforeAll)(async () => {
159
- // Copy project and add existing Sentry setup
160
- fs.cpSync(baseProjectDir, projectDir, { recursive: true });
184
+ // Add existing Sentry setup to the isolated test app
161
185
  const clientEntryPath = path.join(projectDir, 'app', 'entry.client.tsx');
162
186
  const existingContent = `import * as Sentry from "@sentry/react-router";
163
187
  import { startTransition, StrictMode } from "react";
@@ -178,28 +202,27 @@ startTransition(() => {
178
202
  );
179
203
  });`;
180
204
  fs.writeFileSync(clientEntryPath, existingContent);
181
- await runWizardOnReactRouterProject(projectDir, integration);
205
+ wizardExitCode = await runWizardOnReactRouterProject(projectDir, {
206
+ modifiedFiles: true,
207
+ });
182
208
  });
183
209
  (0, vitest_1.afterAll)(() => {
184
- (0, utils_1.revertLocalChanges)(projectDir);
185
- (0, utils_1.cleanupGit)(projectDir);
186
- try {
187
- fs.rmSync(projectDir, { recursive: true, force: true });
188
- }
189
- catch (e) {
190
- // Ignore cleanup errors
191
- }
210
+ cleanup();
211
+ });
212
+ (0, vitest_1.test)('exits with exit code 0', () => {
213
+ (0, vitest_1.expect)(wizardExitCode).toBe(0);
192
214
  });
193
215
  (0, vitest_1.test)('wizard handles existing Sentry without duplication', () => {
194
216
  const clientContent = fs.readFileSync(`${projectDir}/app/entry.client.tsx`, 'utf8');
195
217
  const sentryImportCount = (clientContent.match(/import \* as Sentry from "@sentry\/react-router"/g) || []).length;
196
- const sentryInitCount = (clientContent.match(/Sentry\.init\(/g) || []).length;
218
+ const sentryInitCount = (clientContent.match(/Sentry\.init\(/g) || [])
219
+ .length;
197
220
  (0, vitest_1.expect)(sentryImportCount).toBe(1);
198
221
  (0, vitest_1.expect)(sentryInitCount).toBe(1);
199
222
  });
200
223
  // Only test the essential checks for this edge case
201
224
  (0, vitest_1.test)('package.json is updated correctly', () => {
202
- (0, utils_1.checkPackageJson)(projectDir, integration);
225
+ (0, utils_1.checkPackageJson)(projectDir, '@sentry/react-router');
203
226
  });
204
227
  (0, vitest_1.test)('essential files exist or wizard completes gracefully', () => {
205
228
  // Check if key directories exist
@@ -211,42 +234,37 @@ startTransition(() => {
211
234
  (0, vitest_1.expect)(fs.existsSync(packageJsonPath)).toBe(true);
212
235
  const packageJsonContent = fs.readFileSync(packageJsonPath, 'utf8');
213
236
  const packageJson = JSON.parse(packageJsonContent);
214
- const hasSentryPackage = (packageJson.dependencies?.['@sentry/react-router']) ||
215
- (packageJson.devDependencies?.['@sentry/react-router']);
237
+ const hasSentryPackage = packageJson.dependencies?.['@sentry/react-router'] ||
238
+ packageJson.devDependencies?.['@sentry/react-router'];
216
239
  // The wizard should have at least installed the Sentry package
217
240
  (0, vitest_1.expect)(hasSentryPackage).toBeTruthy();
218
241
  });
219
242
  });
220
243
  (0, vitest_1.describe)('missing entry files', () => {
221
- const integration = Constants_1.Integration.reactRouter;
222
- const projectDir = path.resolve(__dirname, '../test-applications/react-router-test-app-missing-entries');
244
+ let wizardExitCode;
245
+ const { projectDir, cleanup } = (0, utils_1.createIsolatedTestEnv)('react-router-test-app');
223
246
  (0, vitest_1.beforeAll)(async () => {
224
247
  // Copy project and remove entry files
225
- fs.cpSync(baseProjectDir, projectDir, { recursive: true });
226
248
  const entryClientPath = path.join(projectDir, 'app', 'entry.client.tsx');
227
249
  const entryServerPath = path.join(projectDir, 'app', 'entry.server.tsx');
228
250
  if (fs.existsSync(entryClientPath))
229
251
  fs.unlinkSync(entryClientPath);
230
252
  if (fs.existsSync(entryServerPath))
231
253
  fs.unlinkSync(entryServerPath);
232
- await runWizardOnReactRouterProject(projectDir, integration);
254
+ wizardExitCode = await runWizardOnReactRouterProject(projectDir);
233
255
  });
234
256
  (0, vitest_1.afterAll)(() => {
235
- (0, utils_1.revertLocalChanges)(projectDir);
236
- (0, utils_1.cleanupGit)(projectDir);
237
- try {
238
- fs.rmSync(projectDir, { recursive: true, force: true });
239
- }
240
- catch (e) {
241
- // Ignore cleanup errors
242
- }
257
+ cleanup();
258
+ });
259
+ (0, vitest_1.test)('exits with exit code 0', () => {
260
+ (0, vitest_1.expect)(wizardExitCode).toBe(0);
243
261
  });
244
262
  (0, vitest_1.test)('wizard creates missing entry files', () => {
245
263
  (0, utils_1.checkFileExists)(`${projectDir}/app/entry.client.tsx`);
246
264
  (0, utils_1.checkFileExists)(`${projectDir}/app/entry.server.tsx`);
247
265
  });
248
266
  (0, vitest_1.test)('basic configuration still works', () => {
249
- (0, utils_1.checkPackageJson)(projectDir, integration);
267
+ (0, utils_1.checkPackageJson)(projectDir, '@sentry/react-router');
250
268
  (0, utils_1.checkFileExists)(`${projectDir}/instrument.server.mjs`);
251
269
  });
252
270
  });