@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.
- package/CHANGELOG.md +28 -0
- package/LICENSE +97 -8
- package/dist/bin.js +5 -0
- package/dist/bin.js.map +1 -1
- package/dist/e2e-tests/tests/help-message.test.js +5 -1
- package/dist/e2e-tests/tests/help-message.test.js.map +1 -1
- package/dist/e2e-tests/tests/nextjs-15.test.js +79 -0
- package/dist/e2e-tests/tests/nextjs-15.test.js.map +1 -1
- package/dist/e2e-tests/tests/pnpm-workspace.test.d.ts +1 -0
- package/dist/e2e-tests/tests/pnpm-workspace.test.js +206 -0
- package/dist/e2e-tests/tests/pnpm-workspace.test.js.map +1 -0
- package/dist/e2e-tests/tests/react-router.test.d.ts +1 -0
- package/dist/e2e-tests/tests/react-router.test.js +255 -0
- package/dist/e2e-tests/tests/react-router.test.js.map +1 -0
- package/dist/e2e-tests/utils/index.d.ts +8 -2
- package/dist/e2e-tests/utils/index.js +72 -21
- package/dist/e2e-tests/utils/index.js.map +1 -1
- package/dist/lib/Constants.d.ts +1 -0
- package/dist/lib/Constants.js +5 -0
- package/dist/lib/Constants.js.map +1 -1
- package/dist/src/android/android-wizard.js +8 -1
- package/dist/src/android/android-wizard.js.map +1 -1
- package/dist/src/angular/angular-wizard.js +8 -1
- package/dist/src/angular/angular-wizard.js.map +1 -1
- package/dist/src/apple/apple-wizard.js +8 -1
- package/dist/src/apple/apple-wizard.js.map +1 -1
- package/dist/src/flutter/flutter-wizard.js +8 -1
- package/dist/src/flutter/flutter-wizard.js.map +1 -1
- package/dist/src/nextjs/nextjs-wizard.js +35 -9
- package/dist/src/nextjs/nextjs-wizard.js.map +1 -1
- package/dist/src/nextjs/templates.d.ts +3 -3
- package/dist/src/nextjs/templates.js +18 -7
- package/dist/src/nextjs/templates.js.map +1 -1
- package/dist/src/nuxt/nuxt-wizard.js +8 -1
- package/dist/src/nuxt/nuxt-wizard.js.map +1 -1
- package/dist/src/react-native/react-native-wizard.js +8 -1
- package/dist/src/react-native/react-native-wizard.js.map +1 -1
- package/dist/src/react-router/codemods/client.entry.d.ts +1 -0
- package/dist/src/react-router/codemods/client.entry.js +73 -0
- package/dist/src/react-router/codemods/client.entry.js.map +1 -0
- package/dist/src/react-router/codemods/react-router-config.d.ts +9 -0
- package/dist/src/react-router/codemods/react-router-config.js +178 -0
- package/dist/src/react-router/codemods/react-router-config.js.map +1 -0
- package/dist/src/react-router/codemods/root.d.ts +1 -0
- package/dist/src/react-router/codemods/root.js +171 -0
- package/dist/src/react-router/codemods/root.js.map +1 -0
- package/dist/src/react-router/codemods/routes-config.d.ts +1 -0
- package/dist/src/react-router/codemods/routes-config.js +106 -0
- package/dist/src/react-router/codemods/routes-config.js.map +1 -0
- package/dist/src/react-router/codemods/server-entry.d.ts +4 -0
- package/dist/src/react-router/codemods/server-entry.js +275 -0
- package/dist/src/react-router/codemods/server-entry.js.map +1 -0
- package/dist/src/react-router/codemods/utils.d.ts +2 -0
- package/dist/src/react-router/codemods/utils.js +13 -0
- package/dist/src/react-router/codemods/utils.js.map +1 -0
- package/dist/src/react-router/codemods/vite.d.ts +8 -0
- package/dist/src/react-router/codemods/vite.js +169 -0
- package/dist/src/react-router/codemods/vite.js.map +1 -0
- package/dist/src/react-router/react-router-wizard.d.ts +2 -0
- package/dist/src/react-router/react-router-wizard.js +254 -0
- package/dist/src/react-router/react-router-wizard.js.map +1 -0
- package/dist/src/react-router/sdk-example.d.ts +18 -0
- package/dist/src/react-router/sdk-example.js +306 -0
- package/dist/src/react-router/sdk-example.js.map +1 -0
- package/dist/src/react-router/sdk-setup.d.ts +17 -0
- package/dist/src/react-router/sdk-setup.js +250 -0
- package/dist/src/react-router/sdk-setup.js.map +1 -0
- package/dist/src/react-router/templates.d.ts +11 -0
- package/dist/src/react-router/templates.js +273 -0
- package/dist/src/react-router/templates.js.map +1 -0
- package/dist/src/remix/remix-wizard.js +8 -1
- package/dist/src/remix/remix-wizard.js.map +1 -1
- package/dist/src/run.d.ts +2 -1
- package/dist/src/run.js +6 -0
- package/dist/src/run.js.map +1 -1
- package/dist/src/sourcemaps/sourcemaps-wizard.js +8 -1
- package/dist/src/sourcemaps/sourcemaps-wizard.js.map +1 -1
- package/dist/src/sveltekit/sveltekit-wizard.js +8 -1
- package/dist/src/sveltekit/sveltekit-wizard.js.map +1 -1
- package/dist/src/utils/ast-utils.d.ts +30 -0
- package/dist/src/utils/ast-utils.js +71 -1
- package/dist/src/utils/ast-utils.js.map +1 -1
- package/dist/src/utils/clack/index.d.ts +5 -2
- package/dist/src/utils/clack/index.js +8 -0
- package/dist/src/utils/clack/index.js.map +1 -1
- package/dist/src/utils/package-json.js +86 -2
- package/dist/src/utils/package-json.js.map +1 -1
- package/dist/src/utils/types.d.ts +9 -0
- package/dist/src/utils/types.js.map +1 -1
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.js +1 -1
- package/dist/src/version.js.map +1 -1
- package/dist/test/nextjs/templates.test.js +20 -0
- package/dist/test/nextjs/templates.test.js.map +1 -1
- package/dist/test/react-router/codemods/client-entry.test.d.ts +1 -0
- package/dist/test/react-router/codemods/client-entry.test.js +168 -0
- package/dist/test/react-router/codemods/client-entry.test.js.map +1 -0
- package/dist/test/react-router/codemods/react-router-config.test.d.ts +1 -0
- package/dist/test/react-router/codemods/react-router-config.test.js +168 -0
- package/dist/test/react-router/codemods/react-router-config.test.js.map +1 -0
- package/dist/test/react-router/codemods/root.test.d.ts +1 -0
- package/dist/test/react-router/codemods/root.test.js +178 -0
- package/dist/test/react-router/codemods/root.test.js.map +1 -0
- package/dist/test/react-router/codemods/server-entry.test.d.ts +1 -0
- package/dist/test/react-router/codemods/server-entry.test.js +415 -0
- package/dist/test/react-router/codemods/server-entry.test.js.map +1 -0
- package/dist/test/react-router/codemods/vite.test.d.ts +1 -0
- package/dist/test/react-router/codemods/vite.test.js +158 -0
- package/dist/test/react-router/codemods/vite.test.js.map +1 -0
- package/dist/test/react-router/routes-config.test.d.ts +1 -0
- package/dist/test/react-router/routes-config.test.js +156 -0
- package/dist/test/react-router/routes-config.test.js.map +1 -0
- package/dist/test/react-router/sdk-setup.test.d.ts +1 -0
- package/dist/test/react-router/sdk-setup.test.js +411 -0
- package/dist/test/react-router/sdk-setup.test.js.map +1 -0
- package/dist/test/react-router/templates.test.d.ts +1 -0
- package/dist/test/react-router/templates.test.js +220 -0
- package/dist/test/react-router/templates.test.js.map +1 -0
- package/dist/test/utils/package-json.test.d.ts +1 -0
- package/dist/test/utils/package-json.test.js +428 -0
- package/dist/test/utils/package-json.test.js.map +1 -0
- 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
|
|
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
|
-
//
|
|
234
|
-
(
|
|
235
|
-
|
|
236
|
-
|
|
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
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
'--preSelectedProject.dsn',
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
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
|
-
|
|
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
|
/**
|