@sentry/wizard 6.6.1 → 6.8.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 (122) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/LICENSE +97 -8
  3. package/dist/bin.js +5 -0
  4. package/dist/bin.js.map +1 -1
  5. package/dist/e2e-tests/tests/help-message.test.js +5 -1
  6. package/dist/e2e-tests/tests/help-message.test.js.map +1 -1
  7. package/dist/e2e-tests/tests/nextjs-15.test.js +79 -0
  8. package/dist/e2e-tests/tests/nextjs-15.test.js.map +1 -1
  9. package/dist/e2e-tests/tests/pnpm-workspace.test.d.ts +1 -0
  10. package/dist/e2e-tests/tests/pnpm-workspace.test.js +206 -0
  11. package/dist/e2e-tests/tests/pnpm-workspace.test.js.map +1 -0
  12. package/dist/e2e-tests/tests/react-router.test.d.ts +1 -0
  13. package/dist/e2e-tests/tests/react-router.test.js +255 -0
  14. package/dist/e2e-tests/tests/react-router.test.js.map +1 -0
  15. package/dist/e2e-tests/utils/index.d.ts +8 -2
  16. package/dist/e2e-tests/utils/index.js +72 -21
  17. package/dist/e2e-tests/utils/index.js.map +1 -1
  18. package/dist/lib/Constants.d.ts +1 -0
  19. package/dist/lib/Constants.js +5 -0
  20. package/dist/lib/Constants.js.map +1 -1
  21. package/dist/src/android/android-wizard.js +8 -1
  22. package/dist/src/android/android-wizard.js.map +1 -1
  23. package/dist/src/angular/angular-wizard.js +8 -1
  24. package/dist/src/angular/angular-wizard.js.map +1 -1
  25. package/dist/src/apple/apple-wizard.js +8 -1
  26. package/dist/src/apple/apple-wizard.js.map +1 -1
  27. package/dist/src/flutter/flutter-wizard.js +8 -1
  28. package/dist/src/flutter/flutter-wizard.js.map +1 -1
  29. package/dist/src/nextjs/nextjs-wizard.js +35 -9
  30. package/dist/src/nextjs/nextjs-wizard.js.map +1 -1
  31. package/dist/src/nextjs/templates.d.ts +3 -3
  32. package/dist/src/nextjs/templates.js +18 -7
  33. package/dist/src/nextjs/templates.js.map +1 -1
  34. package/dist/src/nuxt/nuxt-wizard.js +8 -1
  35. package/dist/src/nuxt/nuxt-wizard.js.map +1 -1
  36. package/dist/src/react-native/react-native-wizard.js +8 -1
  37. package/dist/src/react-native/react-native-wizard.js.map +1 -1
  38. package/dist/src/react-router/codemods/client.entry.d.ts +1 -0
  39. package/dist/src/react-router/codemods/client.entry.js +73 -0
  40. package/dist/src/react-router/codemods/client.entry.js.map +1 -0
  41. package/dist/src/react-router/codemods/react-router-config.d.ts +9 -0
  42. package/dist/src/react-router/codemods/react-router-config.js +178 -0
  43. package/dist/src/react-router/codemods/react-router-config.js.map +1 -0
  44. package/dist/src/react-router/codemods/root.d.ts +1 -0
  45. package/dist/src/react-router/codemods/root.js +171 -0
  46. package/dist/src/react-router/codemods/root.js.map +1 -0
  47. package/dist/src/react-router/codemods/routes-config.d.ts +1 -0
  48. package/dist/src/react-router/codemods/routes-config.js +106 -0
  49. package/dist/src/react-router/codemods/routes-config.js.map +1 -0
  50. package/dist/src/react-router/codemods/server-entry.d.ts +4 -0
  51. package/dist/src/react-router/codemods/server-entry.js +275 -0
  52. package/dist/src/react-router/codemods/server-entry.js.map +1 -0
  53. package/dist/src/react-router/codemods/utils.d.ts +2 -0
  54. package/dist/src/react-router/codemods/utils.js +13 -0
  55. package/dist/src/react-router/codemods/utils.js.map +1 -0
  56. package/dist/src/react-router/codemods/vite.d.ts +8 -0
  57. package/dist/src/react-router/codemods/vite.js +169 -0
  58. package/dist/src/react-router/codemods/vite.js.map +1 -0
  59. package/dist/src/react-router/react-router-wizard.d.ts +2 -0
  60. package/dist/src/react-router/react-router-wizard.js +254 -0
  61. package/dist/src/react-router/react-router-wizard.js.map +1 -0
  62. package/dist/src/react-router/sdk-example.d.ts +18 -0
  63. package/dist/src/react-router/sdk-example.js +306 -0
  64. package/dist/src/react-router/sdk-example.js.map +1 -0
  65. package/dist/src/react-router/sdk-setup.d.ts +17 -0
  66. package/dist/src/react-router/sdk-setup.js +250 -0
  67. package/dist/src/react-router/sdk-setup.js.map +1 -0
  68. package/dist/src/react-router/templates.d.ts +11 -0
  69. package/dist/src/react-router/templates.js +273 -0
  70. package/dist/src/react-router/templates.js.map +1 -0
  71. package/dist/src/remix/remix-wizard.js +8 -1
  72. package/dist/src/remix/remix-wizard.js.map +1 -1
  73. package/dist/src/run.d.ts +2 -1
  74. package/dist/src/run.js +6 -0
  75. package/dist/src/run.js.map +1 -1
  76. package/dist/src/sourcemaps/sourcemaps-wizard.js +8 -1
  77. package/dist/src/sourcemaps/sourcemaps-wizard.js.map +1 -1
  78. package/dist/src/sveltekit/sveltekit-wizard.js +8 -1
  79. package/dist/src/sveltekit/sveltekit-wizard.js.map +1 -1
  80. package/dist/src/utils/ast-utils.d.ts +30 -0
  81. package/dist/src/utils/ast-utils.js +71 -1
  82. package/dist/src/utils/ast-utils.js.map +1 -1
  83. package/dist/src/utils/clack/index.d.ts +5 -2
  84. package/dist/src/utils/clack/index.js +8 -0
  85. package/dist/src/utils/clack/index.js.map +1 -1
  86. package/dist/src/utils/package-json.js +86 -2
  87. package/dist/src/utils/package-json.js.map +1 -1
  88. package/dist/src/utils/types.d.ts +9 -0
  89. package/dist/src/utils/types.js.map +1 -1
  90. package/dist/src/version.d.ts +1 -1
  91. package/dist/src/version.js +1 -1
  92. package/dist/src/version.js.map +1 -1
  93. package/dist/test/nextjs/templates.test.js +20 -0
  94. package/dist/test/nextjs/templates.test.js.map +1 -1
  95. package/dist/test/react-router/codemods/client-entry.test.d.ts +1 -0
  96. package/dist/test/react-router/codemods/client-entry.test.js +168 -0
  97. package/dist/test/react-router/codemods/client-entry.test.js.map +1 -0
  98. package/dist/test/react-router/codemods/react-router-config.test.d.ts +1 -0
  99. package/dist/test/react-router/codemods/react-router-config.test.js +168 -0
  100. package/dist/test/react-router/codemods/react-router-config.test.js.map +1 -0
  101. package/dist/test/react-router/codemods/root.test.d.ts +1 -0
  102. package/dist/test/react-router/codemods/root.test.js +178 -0
  103. package/dist/test/react-router/codemods/root.test.js.map +1 -0
  104. package/dist/test/react-router/codemods/server-entry.test.d.ts +1 -0
  105. package/dist/test/react-router/codemods/server-entry.test.js +415 -0
  106. package/dist/test/react-router/codemods/server-entry.test.js.map +1 -0
  107. package/dist/test/react-router/codemods/vite.test.d.ts +1 -0
  108. package/dist/test/react-router/codemods/vite.test.js +158 -0
  109. package/dist/test/react-router/codemods/vite.test.js.map +1 -0
  110. package/dist/test/react-router/routes-config.test.d.ts +1 -0
  111. package/dist/test/react-router/routes-config.test.js +156 -0
  112. package/dist/test/react-router/routes-config.test.js.map +1 -0
  113. package/dist/test/react-router/sdk-setup.test.d.ts +1 -0
  114. package/dist/test/react-router/sdk-setup.test.js +411 -0
  115. package/dist/test/react-router/sdk-setup.test.js.map +1 -0
  116. package/dist/test/react-router/templates.test.d.ts +1 -0
  117. package/dist/test/react-router/templates.test.js +220 -0
  118. package/dist/test/react-router/templates.test.js.map +1 -0
  119. package/dist/test/utils/package-json.test.d.ts +1 -0
  120. package/dist/test/utils/package-json.test.js +428 -0
  121. package/dist/test/utils/package-json.test.js.map +1 -0
  122. package/package.json +4 -2
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pnpm-workspace.test.js","sourceRoot":"","sources":["../../../e2e-tests/tests/pnpm-workspace.test.ts"],"names":[],"mappings":"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","sourcesContent":["import * as path from 'node:path';\nimport * as fs from 'node:fs';\nimport { Integration } from '../../lib/Constants';\nimport {\n checkEnvBuildPlugin,\n checkFileExists,\n checkIfBuilds,\n checkIfRunsOnDevMode,\n checkIfRunsOnProdMode,\n checkPackageJson,\n cleanupGit,\n getWizardCommand,\n initGit,\n revertLocalChanges,\n TEST_ARGS,\n} from '../utils';\nimport { afterAll, beforeAll, describe, expect, it } from 'vitest';\n\n//@ts-expect-error - clifty is ESM only\nimport { KEYS, withEnv } from 'clifty';\n\ndescribe('pnpm workspace', () => {\n const workspaceDir = path.resolve(\n __dirname,\n '../test-applications/pnpm-workspace-test-app',\n );\n const projectDir = path.resolve(workspaceDir, 'packages/sveltekit');\n\n const integration = Integration.sveltekit;\n let wizardExitCode: number;\n\n beforeAll(async () => {\n initGit(workspaceDir);\n revertLocalChanges(workspaceDir);\n\n wizardExitCode = await withEnv({\n cwd: projectDir,\n })\n .defineInteraction()\n .expectOutput(\n 'The Sentry SvelteKit Wizard will help you set up Sentry for your application',\n )\n .step('package installation', ({ expectOutput, whenAsked }) => {\n whenAsked('Please select your package manager.').respondWith(\n KEYS.DOWN,\n KEYS.DOWN,\n KEYS.DOWN,\n KEYS.ENTER,\n );\n expectOutput('Installing @sentry/sveltekit');\n })\n .step('SDK setup', ({ whenAsked }) => {\n whenAsked('Do you want to enable Tracing', {\n timeout: 90_000, // package installation can take a while in CI\n }).respondWith(KEYS.ENTER);\n whenAsked('Do you want to enable Session Replay').respondWith(\n KEYS.ENTER,\n );\n whenAsked('Do you want to enable Logs').respondWith(KEYS.ENTER);\n })\n .whenAsked('Do you want to create an example page')\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 SvelteKit SDK!')\n .run(getWizardCommand(integration));\n });\n\n afterAll(() => {\n revertLocalChanges(workspaceDir);\n cleanupGit(workspaceDir);\n });\n\n it('exits with exit code 0', () => {\n expect(wizardExitCode).toBe(0);\n });\n\n it('adds the SDK dependency to package.json', () => {\n checkPackageJson(projectDir, integration);\n });\n\n it('adds the .env.sentry-build-plugin', () => {\n checkEnvBuildPlugin(projectDir);\n });\n\n it('adds the example page', () => {\n checkFileExists(\n path.resolve(projectDir, 'src/routes/sentry-example-page/+page.svelte'),\n );\n checkFileExists(\n path.resolve(projectDir, 'src/routes/sentry-example-page/+server.js'),\n );\n });\n\n it('adds the sentry plugin to vite.config.ts', () => {\n const viteConfig = fs.readFileSync(\n path.resolve(projectDir, 'vite.config.ts'),\n );\n expect(viteConfig.toString()).toMatchInlineSnapshot(`\n \"import { sentrySvelteKit } from \"@sentry/sveltekit\";\n import { sveltekit } from '@sveltejs/kit/vite';\n import { defineConfig } from 'vite';\n\n export default defineConfig({\n \tplugins: [sentrySvelteKit({\n sourceMapsUploadOptions: {\n org: \"${TEST_ARGS.ORG_SLUG}\",\n project: \"${TEST_ARGS.PROJECT_SLUG}\"\n }\n }), sveltekit()]\n });\"\n `);\n });\n\n it('creates the hook files', () => {\n const clientHooks = fs.readFileSync(\n path.resolve(projectDir, 'src/hooks.client.ts'),\n );\n const serverHooks = fs.readFileSync(\n path.resolve(projectDir, 'src/hooks.server.ts'),\n );\n\n expect(clientHooks.toString()).toMatchInlineSnapshot(`\n \"import { handleErrorWithSentry, replayIntegration } from \"@sentry/sveltekit\";\n import * as Sentry from '@sentry/sveltekit';\n\n Sentry.init({\n dsn: '${TEST_ARGS.PROJECT_DSN}',\n\n tracesSampleRate: 1.0,\n\n // Enable logs to be sent to Sentry\n enableLogs: true,\n\n // This sets the sample rate to be 10%. You may want this to be 100% while\n // in development and sample at a lower rate in production\n replaysSessionSampleRate: 0.1,\n\n // If the entire session is not sampled, use the below sample rate to sample\n // sessions when an error occurs.\n replaysOnErrorSampleRate: 1.0,\n\n // If you don't want to use Session Replay, just remove the line below:\n integrations: [replayIntegration()],\n\n // Enable sending user PII (Personally Identifiable Information)\n // https://docs.sentry.io/platforms/javascript/guides/sveltekit/configuration/options/#sendDefaultPii\n sendDefaultPii: true,\n });\n\n // If you have a custom error handler, pass it to \\`handleErrorWithSentry\\`\n export const handleError = handleErrorWithSentry();\n \"\n `);\n\n expect(serverHooks.toString()).toMatchInlineSnapshot(`\n \"import {sequence} from \"@sveltejs/kit/hooks\";\n import * as Sentry from \"@sentry/sveltekit\";\n export const handle = sequence(Sentry.sentryHandle(), async ({ event, resolve }) => {\n const response = await resolve(event);\n return response;\n });\n export const handleError = Sentry.handleErrorWithSentry();\"\n `);\n });\n\n it('creates the insturmentation.server file', () => {\n const instrumentationServer = fs.readFileSync(\n path.resolve(projectDir, 'src/instrumentation.server.ts'),\n );\n\n expect(instrumentationServer.toString()).toMatchInlineSnapshot(`\n \"import * as Sentry from '@sentry/sveltekit';\n\n Sentry.init({\n dsn: '${TEST_ARGS.PROJECT_DSN}',\n\n tracesSampleRate: 1.0,\n\n // Enable logs to be sent to Sentry\n enableLogs: true,\n\n // uncomment the line below to enable Spotlight (https://spotlightjs.com)\n // spotlight: import.meta.env.DEV,\n });\"\n `);\n });\n\n it('enables tracing and instrumentation in svelte.config.js', () => {\n const svelteConfig = fs.readFileSync(\n path.resolve(projectDir, 'svelte.config.js'),\n );\n expect(svelteConfig.toString()).toMatchInlineSnapshot(`\n \"import adapter from '@sveltejs/adapter-node';\n import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';\n\n /** @type {import('@sveltejs/kit').Config} */\n const config = {\n // Consult https://svelte.dev/docs/kit/integrations#preprocessors\n // for more information about preprocessors\n preprocess: vitePreprocess(),\n\n kit: {\n // adapter-auto only supports some environments, see https://svelte.dev/docs/kit/adapter-auto for a list.\n // If your environment is not supported, or you settled on a specific environment, switch out the adapter.\n // See https://svelte.dev/docs/kit/adapters for more information about adapters.\n adapter: adapter(),\n experimental: {\n remoteFunctions: true,\n\n tracing: {\n server: true,\n },\n\n instrumentation: {\n server: true,\n },\n },\n },\n };\n\n export default config;\"\n `);\n });\n\n // checkSvelteKitProject(projectDir, integration);\n it('builds successfully', async () => {\n await checkIfBuilds(projectDir);\n });\n\n it('runs on dev mode correctly', async () => {\n await checkIfRunsOnDevMode(projectDir, 'ready in');\n });\n\n it('runs on prod mode correctly', async () => {\n await checkIfRunsOnProdMode(projectDir, 'to expose', 'preview');\n });\n});\n"]}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,255 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ const path = __importStar(require("node:path"));
27
+ const fs = __importStar(require("node:fs"));
28
+ const Constants_1 = require("../../lib/Constants");
29
+ const utils_1 = require("../utils");
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
139
+ }
140
+ (0, vitest_1.describe)('React Router', () => {
141
+ (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');
144
+ (0, vitest_1.beforeAll)(async () => {
145
+ await runWizardOnReactRouterProject(projectDir, integration);
146
+ });
147
+ (0, vitest_1.afterAll)(() => {
148
+ (0, utils_1.revertLocalChanges)(projectDir);
149
+ (0, utils_1.cleanupGit)(projectDir);
150
+ });
151
+ checkReactRouterProject(projectDir, integration);
152
+ });
153
+ (0, vitest_1.describe)('edge cases', () => {
154
+ const baseProjectDir = path.resolve(__dirname, '../test-applications/react-router-test-app');
155
+ (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');
158
+ (0, vitest_1.beforeAll)(async () => {
159
+ // Copy project and add existing Sentry setup
160
+ fs.cpSync(baseProjectDir, projectDir, { recursive: true });
161
+ const clientEntryPath = path.join(projectDir, 'app', 'entry.client.tsx');
162
+ const existingContent = `import * as Sentry from "@sentry/react-router";
163
+ import { startTransition, StrictMode } from "react";
164
+ import { hydrateRoot } from "react-dom/client";
165
+ import { HydratedRouter } from "react-router/dom";
166
+
167
+ Sentry.init({
168
+ dsn: "https://existing@dsn.ingest.sentry.io/1337",
169
+ tracesSampleRate: 1.0,
170
+ });
171
+
172
+ startTransition(() => {
173
+ hydrateRoot(
174
+ document,
175
+ <StrictMode>
176
+ <HydratedRouter />
177
+ </StrictMode>
178
+ );
179
+ });`;
180
+ fs.writeFileSync(clientEntryPath, existingContent);
181
+ await runWizardOnReactRouterProject(projectDir, integration);
182
+ });
183
+ (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
+ }
192
+ });
193
+ (0, vitest_1.test)('wizard handles existing Sentry without duplication', () => {
194
+ const clientContent = fs.readFileSync(`${projectDir}/app/entry.client.tsx`, 'utf8');
195
+ const sentryImportCount = (clientContent.match(/import \* as Sentry from "@sentry\/react-router"/g) || []).length;
196
+ const sentryInitCount = (clientContent.match(/Sentry\.init\(/g) || []).length;
197
+ (0, vitest_1.expect)(sentryImportCount).toBe(1);
198
+ (0, vitest_1.expect)(sentryInitCount).toBe(1);
199
+ });
200
+ // Only test the essential checks for this edge case
201
+ (0, vitest_1.test)('package.json is updated correctly', () => {
202
+ (0, utils_1.checkPackageJson)(projectDir, integration);
203
+ });
204
+ (0, vitest_1.test)('essential files exist or wizard completes gracefully', () => {
205
+ // Check if key directories exist
206
+ (0, vitest_1.expect)(fs.existsSync(`${projectDir}/app`)).toBe(true);
207
+ // When there's existing Sentry setup, the wizard may skip some file creation
208
+ // to avoid conflicts. This is acceptable behavior.
209
+ // Let's check if the wizard at least completed by verifying package.json was updated
210
+ const packageJsonPath = `${projectDir}/package.json`;
211
+ (0, vitest_1.expect)(fs.existsSync(packageJsonPath)).toBe(true);
212
+ const packageJsonContent = fs.readFileSync(packageJsonPath, 'utf8');
213
+ const packageJson = JSON.parse(packageJsonContent);
214
+ const hasSentryPackage = (packageJson.dependencies?.['@sentry/react-router']) ||
215
+ (packageJson.devDependencies?.['@sentry/react-router']);
216
+ // The wizard should have at least installed the Sentry package
217
+ (0, vitest_1.expect)(hasSentryPackage).toBeTruthy();
218
+ });
219
+ });
220
+ (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');
223
+ (0, vitest_1.beforeAll)(async () => {
224
+ // Copy project and remove entry files
225
+ fs.cpSync(baseProjectDir, projectDir, { recursive: true });
226
+ const entryClientPath = path.join(projectDir, 'app', 'entry.client.tsx');
227
+ const entryServerPath = path.join(projectDir, 'app', 'entry.server.tsx');
228
+ if (fs.existsSync(entryClientPath))
229
+ fs.unlinkSync(entryClientPath);
230
+ if (fs.existsSync(entryServerPath))
231
+ fs.unlinkSync(entryServerPath);
232
+ await runWizardOnReactRouterProject(projectDir, integration);
233
+ });
234
+ (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
+ }
243
+ });
244
+ (0, vitest_1.test)('wizard creates missing entry files', () => {
245
+ (0, utils_1.checkFileExists)(`${projectDir}/app/entry.client.tsx`);
246
+ (0, utils_1.checkFileExists)(`${projectDir}/app/entry.server.tsx`);
247
+ });
248
+ (0, vitest_1.test)('basic configuration still works', () => {
249
+ (0, utils_1.checkPackageJson)(projectDir, integration);
250
+ (0, utils_1.checkFileExists)(`${projectDir}/instrument.server.mjs`);
251
+ });
252
+ });
253
+ });
254
+ });
255
+ //# sourceMappingURL=react-router.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react-router.test.js","sourceRoot":"","sources":["../../../e2e-tests/tests/react-router.test.ts"],"names":[],"mappings":"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","sourcesContent":["import * as path from 'node:path';\nimport * as fs from 'node:fs';\nimport { Integration } from '../../lib/Constants';\nimport {\n KEYS,\n TEST_ARGS,\n checkEnvBuildPlugin,\n checkFileContents,\n checkFileExists,\n checkIfBuilds,\n checkIfRunsOnDevMode,\n checkIfRunsOnProdMode,\n checkPackageJson,\n cleanupGit,\n revertLocalChanges,\n startWizardInstance,\n} from '../utils';\nimport { afterAll, beforeAll, describe, test, expect } from 'vitest';\n\nasync function runWizardOnReactRouterProject(\n projectDir: string,\n integration: Integration,\n) {\n const wizardInstance = startWizardInstance(integration, projectDir);\n\n const packageManagerPrompted = await wizardInstance.waitForOutput(\n 'Please select your package manager.',\n );\n\n const tracingOptionPrompted =\n packageManagerPrompted &&\n (await wizardInstance.sendStdinAndWaitForOutput(\n [KEYS.DOWN, KEYS.ENTER],\n 'to track the performance of your application?',\n { timeout: 240_000 }\n ));\n\n const replayOptionPrompted =\n tracingOptionPrompted &&\n (await wizardInstance.sendStdinAndWaitForOutput(\n [KEYS.ENTER],\n 'to get a video-like reproduction of errors during a user session?'\n ));\n\n const logOptionPrompted =\n replayOptionPrompted &&\n (await wizardInstance.sendStdinAndWaitForOutput(\n [KEYS.ENTER],\n 'to send your application logs to Sentry?'\n ));\n\n const profilingOptionPrompted =\n logOptionPrompted &&\n (await wizardInstance.sendStdinAndWaitForOutput(\n [KEYS.ENTER],\n 'to track application performance in detail?'\n ));\n\n const examplePagePrompted =\n profilingOptionPrompted &&\n (await wizardInstance.sendStdinAndWaitForOutput(\n [KEYS.ENTER],\n 'Do you want to create an example page'\n ));\n\n const mcpPrompted =\n examplePagePrompted &&\n (await wizardInstance.sendStdinAndWaitForOutput(\n [KEYS.ENTER],\n 'Optionally add a project-scoped MCP server configuration for the Sentry MCP?',\n { optional: true }\n ));\n\n mcpPrompted &&\n (await wizardInstance.sendStdinAndWaitForOutput(\n [KEYS.DOWN, KEYS.ENTER],\n 'Successfully installed the Sentry React Router SDK!'\n ));\n\n wizardInstance.kill();\n}\n\nfunction checkReactRouterProject(projectDir: string, integration: Integration) {\n test('package.json is updated correctly', () => {\n checkPackageJson(projectDir, integration);\n });\n\n test('.env.sentry-build-plugin is created and contains the auth token', () => {\n checkEnvBuildPlugin(projectDir);\n });\n\n test('example page exists', () => {\n checkFileExists(`${projectDir}/app/routes/sentry-example-page.tsx`);\n });\n\n test('example API route exists', () => {\n checkFileExists(`${projectDir}/app/routes/api.sentry-example-api.ts`);\n });\n\n test('example page is added to routes configuration', () => {\n checkFileContents(`${projectDir}/app/routes.ts`, [\n 'route(\"/sentry-example-page\", \"routes/sentry-example-page.tsx\")',\n 'route(\"/api/sentry-example-api\", \"routes/api.sentry-example-api.ts\")',\n ]);\n });\n\n test('instrument.server file exists', () => {\n checkFileExists(`${projectDir}/instrument.server.mjs`);\n });\n\n test('entry.client file contains Sentry initialization', () => {\n checkFileContents(`${projectDir}/app/entry.client.tsx`, [\n 'import * as Sentry from',\n '@sentry/react-router',\n `Sentry.init({\n dsn: \"${TEST_ARGS.PROJECT_DSN}\",`,\n 'integrations: [Sentry.reactRouterTracingIntegration(), Sentry.replayIntegration()]',\n 'enableLogs: true,',\n 'tracesSampleRate: 1.0,',\n ]);\n });\n\n test('package.json scripts are updated correctly', () => {\n checkFileContents(`${projectDir}/package.json`, [\n `\"start\": \"NODE_OPTIONS='--import ./instrument.server.mjs' react-router-serve ./build/server/index.js\"`,\n `\"dev\": \"NODE_OPTIONS='--import ./instrument.server.mjs' react-router dev\"`,\n ]);\n });\n\n test('entry.server file contains Sentry instrumentation', () => {\n checkFileContents(`${projectDir}/app/entry.server.tsx`, [\n 'import * as Sentry from',\n '@sentry/react-router',\n 'export const handleError = Sentry.createSentryHandleError(',\n 'export default Sentry.wrapSentryHandleRequest(handleRequest);'\n ]);\n });\n\n test('instrument.server file contains Sentry initialization', () => {\n checkFileContents(`${projectDir}/instrument.server.mjs`, [\n 'import * as Sentry from \\'@sentry/react-router\\';',\n `Sentry.init({\n dsn: \"${TEST_ARGS.PROJECT_DSN}\",`,\n 'enableLogs: true,',\n ]);\n });\n\n test('root file contains Sentry ErrorBoundary', () => {\n checkFileContents(`${projectDir}/app/root.tsx`, [\n 'import * as Sentry from',\n '@sentry/react-router',\n 'export function ErrorBoundary',\n 'Sentry.captureException(error)',\n ]);\n });\n\n test('vite.config file contains sentryReactRouter plugin', () => {\n checkFileContents(`${projectDir}/vite.config.ts`, [\n 'import { sentryReactRouter } from',\n '@sentry/react-router',\n 'sentryReactRouter(',\n 'authToken: process.env.SENTRY_AUTH_TOKEN',\n ]);\n });\n\n test('react-router.config file contains buildEnd hook with sentryOnBuildEnd', () => {\n checkFileContents(`${projectDir}/react-router.config.ts`, [\n 'import { sentryOnBuildEnd } from',\n '@sentry/react-router',\n 'ssr: true,',\n 'buildEnd: async',\n 'await sentryOnBuildEnd({',\n ]);\n });\n\n test('builds successfully', async () => {\n await checkIfBuilds(projectDir);\n }, 60000); // 1 minute timeout\n\n test('runs on dev mode correctly', async () => {\n await checkIfRunsOnDevMode(projectDir, 'to expose');\n }, 30000); // 30 second timeout\n\n test('runs on prod mode correctly', async () => {\n await checkIfRunsOnProdMode(projectDir, 'react-router-serve');\n }, 30000); // 30 second timeout\n}\n\ndescribe('React Router', () => {\n describe('with empty project', () => {\n const integration = Integration.reactRouter;\n const projectDir = path.resolve(\n __dirname,\n '../test-applications/react-router-test-app',\n );\n\n beforeAll(async () => {\n await runWizardOnReactRouterProject(projectDir, integration);\n });\n\n afterAll(() => {\n revertLocalChanges(projectDir);\n cleanupGit(projectDir);\n });\n\n checkReactRouterProject(projectDir, integration);\n });\n\n describe('edge cases', () => {\n const baseProjectDir = path.resolve(\n __dirname,\n '../test-applications/react-router-test-app',\n );\n\n describe('existing Sentry setup', () => {\n const integration = Integration.reactRouter;\n const projectDir = path.resolve(\n __dirname,\n '../test-applications/react-router-test-app-existing',\n );\n\n beforeAll(async () => {\n // Copy project and add existing Sentry setup\n fs.cpSync(baseProjectDir, projectDir, { recursive: true });\n\n const clientEntryPath = path.join(projectDir, 'app', 'entry.client.tsx');\n const existingContent = `import * as Sentry from \"@sentry/react-router\";\nimport { startTransition, StrictMode } from \"react\";\nimport { hydrateRoot } from \"react-dom/client\";\nimport { HydratedRouter } from \"react-router/dom\";\n\nSentry.init({\n dsn: \"https://existing@dsn.ingest.sentry.io/1337\",\n tracesSampleRate: 1.0,\n});\n\nstartTransition(() => {\n hydrateRoot(\n document,\n <StrictMode>\n <HydratedRouter />\n </StrictMode>\n );\n});`;\n fs.writeFileSync(clientEntryPath, existingContent);\n\n await runWizardOnReactRouterProject(projectDir, integration);\n });\n\n afterAll(() => {\n revertLocalChanges(projectDir);\n cleanupGit(projectDir);\n try {\n fs.rmSync(projectDir, { recursive: true, force: true });\n } catch (e) {\n // Ignore cleanup errors\n }\n });\n\n test('wizard handles existing Sentry without duplication', () => {\n const clientContent = fs.readFileSync(`${projectDir}/app/entry.client.tsx`, 'utf8');\n const sentryImportCount = (clientContent.match(/import \\* as Sentry from \"@sentry\\/react-router\"/g) || []).length;\n const sentryInitCount = (clientContent.match(/Sentry\\.init\\(/g) || []).length;\n\n expect(sentryImportCount).toBe(1);\n expect(sentryInitCount).toBe(1);\n });\n\n // Only test the essential checks for this edge case\n test('package.json is updated correctly', () => {\n checkPackageJson(projectDir, integration);\n });\n\n test('essential files exist or wizard completes gracefully', () => {\n // Check if key directories exist\n expect(fs.existsSync(`${projectDir}/app`)).toBe(true);\n\n // When there's existing Sentry setup, the wizard may skip some file creation\n // to avoid conflicts. This is acceptable behavior.\n // Let's check if the wizard at least completed by verifying package.json was updated\n const packageJsonPath = `${projectDir}/package.json`;\n expect(fs.existsSync(packageJsonPath)).toBe(true);\n\n const packageJsonContent = fs.readFileSync(packageJsonPath, 'utf8');\n const packageJson = JSON.parse(packageJsonContent) as {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n };\n\n const hasSentryPackage =\n (packageJson.dependencies?.['@sentry/react-router']) ||\n (packageJson.devDependencies?.['@sentry/react-router']);\n\n // The wizard should have at least installed the Sentry package\n expect(hasSentryPackage).toBeTruthy();\n });\n });\n\n describe('missing entry files', () => {\n const integration = Integration.reactRouter;\n const projectDir = path.resolve(\n __dirname,\n '../test-applications/react-router-test-app-missing-entries',\n );\n\n beforeAll(async () => {\n // Copy project and remove entry files\n fs.cpSync(baseProjectDir, projectDir, { recursive: true });\n\n const entryClientPath = path.join(projectDir, 'app', 'entry.client.tsx');\n const entryServerPath = path.join(projectDir, 'app', 'entry.server.tsx');\n\n if (fs.existsSync(entryClientPath)) fs.unlinkSync(entryClientPath);\n if (fs.existsSync(entryServerPath)) fs.unlinkSync(entryServerPath);\n\n await runWizardOnReactRouterProject(projectDir, integration);\n });\n\n afterAll(() => {\n revertLocalChanges(projectDir);\n cleanupGit(projectDir);\n try {\n fs.rmSync(projectDir, { recursive: true, force: true });\n } catch (e) {\n // Ignore cleanup errors\n }\n });\n\n test('wizard creates missing entry files', () => {\n checkFileExists(`${projectDir}/app/entry.client.tsx`);\n checkFileExists(`${projectDir}/app/entry.server.tsx`);\n });\n\n test('basic configuration still works', () => {\n checkPackageJson(projectDir, integration);\n checkFileExists(`${projectDir}/instrument.server.mjs`);\n });\n });\n });\n});\n"]}
@@ -1,5 +1,5 @@
1
1
  /// <reference types="node" />
2
- import type { Integration } from '../../lib/Constants';
2
+ import { Integration } from '../../lib/Constants';
3
3
  import type { ChildProcess } from 'node:child_process';
4
4
  export declare const KEYS: {
5
5
  UP: string;
@@ -90,7 +90,7 @@ export declare function getWizardCommand(integration: Integration): string;
90
90
  *
91
91
  * @returns WizardTestEnv
92
92
  */
93
- export declare function startWizardInstance(integration: Integration, projectDir: string, debug?: boolean): WizardTestEnv;
93
+ export declare function startWizardInstance(integration: Integration, projectDir: string, debug?: boolean, spotlight?: boolean): WizardTestEnv;
94
94
  /**
95
95
  * Create a file with the given content
96
96
  *
@@ -126,6 +126,12 @@ export declare function checkFileContents(filePath: string, content: string | st
126
126
  * @param filePath
127
127
  */
128
128
  export declare function checkFileExists(filePath: string): void;
129
+ /**
130
+ * Check if the file does not exist
131
+ *
132
+ * @param filePath
133
+ */
134
+ export declare function checkFileDoesNotExist(filePath: string): void;
129
135
  /**
130
136
  * Check if the package.json contains the given integration
131
137
  *
@@ -23,9 +23,10 @@ var __importStar = (this && this.__importStar) || function (mod) {
23
23
  return result;
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.checkIfRunsOnProdMode = exports.checkIfRunsOnDevMode = exports.checkIfExpoBundles = exports.checkIfReactNativeBundles = exports.checkIfFlutterBuilds = exports.checkIfBuilds = exports.checkSentryProperties = exports.checkEnvBuildPlugin = exports.checkSentryCliRc = exports.checkPackageJson = exports.checkFileExists = exports.checkFileContents = exports.checkFileDoesNotContain = exports.modifyFile = exports.createFile = exports.startWizardInstance = exports.getWizardCommand = exports.revertLocalChanges = exports.cleanupGit = exports.initGit = exports.WizardTestEnv = exports.log = exports.TEST_ARGS = exports.KEYS = void 0;
26
+ exports.checkIfRunsOnProdMode = exports.checkIfRunsOnDevMode = exports.checkIfExpoBundles = exports.checkIfReactNativeBundles = exports.checkIfFlutterBuilds = exports.checkIfBuilds = exports.checkSentryProperties = exports.checkEnvBuildPlugin = exports.checkSentryCliRc = exports.checkPackageJson = exports.checkFileDoesNotExist = exports.checkFileExists = exports.checkFileContents = exports.checkFileDoesNotContain = exports.modifyFile = exports.createFile = exports.startWizardInstance = exports.getWizardCommand = exports.revertLocalChanges = exports.cleanupGit = exports.initGit = exports.WizardTestEnv = exports.log = exports.TEST_ARGS = exports.KEYS = void 0;
27
27
  const fs = __importStar(require("node:fs"));
28
28
  const path = __importStar(require("node:path"));
29
+ const Constants_1 = require("../../lib/Constants");
29
30
  const node_child_process_1 = require("node:child_process");
30
31
  const Logging_1 = require("../../lib/Helper/Logging");
31
32
  const vitest_1 = require("vitest");
@@ -230,10 +231,14 @@ exports.cleanupGit = cleanupGit;
230
231
  */
231
232
  function revertLocalChanges(projectDir) {
232
233
  try {
233
- // Revert tracked files
234
- (0, node_child_process_1.execSync)('git restore .', { cwd: projectDir });
235
- // Revert untracked files
236
- (0, node_child_process_1.execSync)('git clean -fd .', { cwd: projectDir });
234
+ // Check if this is a git repository first
235
+ const isGitRepo = fs.existsSync(path.join(projectDir, '.git'));
236
+ if (isGitRepo) {
237
+ // Revert tracked files
238
+ (0, node_child_process_1.execSync)('git restore .', { cwd: projectDir });
239
+ // Revert untracked files
240
+ (0, node_child_process_1.execSync)('git clean -fd .', { cwd: projectDir });
241
+ }
237
242
  // Remove node_modules and dist (.gitignore'd and therefore not removed via git clean)
238
243
  (0, node_child_process_1.execSync)('rm -rf node_modules', { cwd: projectDir });
239
244
  (0, node_child_process_1.execSync)('rm -rf dist', { cwd: projectDir });
@@ -273,7 +278,7 @@ exports.getWizardCommand = getWizardCommand;
273
278
  *
274
279
  * @returns WizardTestEnv
275
280
  */
276
- function startWizardInstance(integration, projectDir, debug = false) {
281
+ function startWizardInstance(integration, projectDir, debug = false, spotlight = false) {
277
282
  const binName = process.env.SENTRY_WIZARD_E2E_TEST_BIN
278
283
  ? ['dist-bin', `sentry-wizard-${process.platform}-${process.arch}`]
279
284
  : ['dist', 'bin.js'];
@@ -281,20 +286,16 @@ function startWizardInstance(integration, projectDir, debug = false) {
281
286
  revertLocalChanges(projectDir);
282
287
  cleanupGit(projectDir);
283
288
  initGit(projectDir);
284
- return new WizardTestEnv(binPath, [
285
- '--debug',
286
- '-i',
287
- integration,
288
- '--preSelectedProject.authToken',
289
- exports.TEST_ARGS.AUTH_TOKEN,
290
- '--preSelectedProject.dsn',
291
- exports.TEST_ARGS.PROJECT_DSN,
292
- '--preSelectedProject.orgSlug',
293
- exports.TEST_ARGS.ORG_SLUG,
294
- '--preSelectedProject.projectSlug',
295
- exports.TEST_ARGS.PROJECT_SLUG,
296
- '--disable-telemetry',
297
- ], { cwd: projectDir, debug });
289
+ const args = ['--debug', '-i', integration];
290
+ if (spotlight) {
291
+ // Spotlight mode: skip authentication
292
+ args.push('--spotlight');
293
+ }
294
+ else {
295
+ args.push('--preSelectedProject.authToken', exports.TEST_ARGS.AUTH_TOKEN, '--preSelectedProject.dsn', exports.TEST_ARGS.PROJECT_DSN, '--preSelectedProject.orgSlug', exports.TEST_ARGS.ORG_SLUG, '--preSelectedProject.projectSlug', exports.TEST_ARGS.PROJECT_SLUG);
296
+ }
297
+ args.push('--disable-telemetry');
298
+ return new WizardTestEnv(binPath, args, { cwd: projectDir, debug });
298
299
  }
299
300
  exports.startWizardInstance = startWizardInstance;
300
301
  /**
@@ -360,6 +361,52 @@ function checkFileExists(filePath) {
360
361
  (0, vitest_1.expect)(fs.existsSync(filePath)).toBe(true);
361
362
  }
362
363
  exports.checkFileExists = checkFileExists;
364
+ /**
365
+ * Check if the file does not exist
366
+ *
367
+ * @param filePath
368
+ */
369
+ function checkFileDoesNotExist(filePath) {
370
+ (0, vitest_1.expect)(fs.existsSync(filePath)).toBe(false);
371
+ }
372
+ exports.checkFileDoesNotExist = checkFileDoesNotExist;
373
+ /**
374
+ * Map integration to its corresponding Sentry package name
375
+ * @param type Integration type
376
+ * @returns Package name or undefined if no package exists
377
+ */
378
+ function mapIntegrationToPackageName(type) {
379
+ switch (type) {
380
+ case Constants_1.Integration.android:
381
+ return undefined; // Android doesn't have a JavaScript package
382
+ case Constants_1.Integration.reactNative:
383
+ return '@sentry/react-native';
384
+ case Constants_1.Integration.flutter:
385
+ return undefined; // Flutter doesn't have a JavaScript package
386
+ case Constants_1.Integration.cordova:
387
+ return '@sentry/cordova';
388
+ case Constants_1.Integration.angular:
389
+ return '@sentry/angular';
390
+ case Constants_1.Integration.electron:
391
+ return '@sentry/electron';
392
+ case Constants_1.Integration.nextjs:
393
+ return '@sentry/nextjs';
394
+ case Constants_1.Integration.nuxt:
395
+ return '@sentry/nuxt';
396
+ case Constants_1.Integration.remix:
397
+ return '@sentry/remix';
398
+ case Constants_1.Integration.reactRouter:
399
+ return '@sentry/react-router';
400
+ case Constants_1.Integration.sveltekit:
401
+ return '@sentry/sveltekit';
402
+ case Constants_1.Integration.sourcemaps:
403
+ return undefined; // Sourcemaps doesn't install a package
404
+ case Constants_1.Integration.ios:
405
+ return undefined; // iOS doesn't have a JavaScript package
406
+ default:
407
+ return undefined;
408
+ }
409
+ }
363
410
  /**
364
411
  * Check if the package.json contains the given integration
365
412
  *
@@ -367,7 +414,11 @@ exports.checkFileExists = checkFileExists;
367
414
  * @param integration
368
415
  */
369
416
  function checkPackageJson(projectDir, integration) {
370
- checkFileContents(`${projectDir}/package.json`, `@sentry/${integration}`);
417
+ const packageName = mapIntegrationToPackageName(integration);
418
+ if (!packageName) {
419
+ throw new Error(`No package name found for integration: ${integration}`);
420
+ }
421
+ checkFileContents(`${projectDir}/package.json`, packageName);
371
422
  }
372
423
  exports.checkPackageJson = checkPackageJson;
373
424
  /**