@sentry/wizard
Version:
Sentry wizard helping you to configure your project
207 lines (205 loc) • 10.1 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs = __importStar(require("node:fs"));
const Constants_1 = require("../../lib/Constants");
const utils_1 = require("../utils");
const utils_2 = require("../utils");
const vitest_1 = require("vitest");
//@ts-expect-error - clifty is ESM only
const clifty_1 = require("clifty");
(0, vitest_1.describe)('NextJS-15', () => {
const integration = Constants_1.Integration.nextjs;
let wizardExitCode;
const { projectDir, cleanup } = (0, utils_1.createIsolatedTestEnv)('nextjs-15-test-app');
(0, vitest_1.beforeAll)(async () => {
wizardExitCode = await (0, clifty_1.withEnv)({
cwd: projectDir,
})
.defineInteraction()
.whenAsked('Please select your package manager.')
.respondWith(clifty_1.KEYS.DOWN, clifty_1.KEYS.ENTER) // Select yarn
.whenAsked('Do you want to route Sentry requests in the browser through your Next.js server', {
timeout: 240000, // package installation can take a while in CI
})
.respondWith(clifty_1.KEYS.ENTER)
.whenAsked('to track the performance of your application?')
.respondWith(clifty_1.KEYS.ENTER)
.whenAsked('to get a video-like reproduction of errors during a user session?')
.respondWith(clifty_1.KEYS.ENTER)
.whenAsked('to send your application logs to Sentry?')
.respondWith(clifty_1.KEYS.ENTER)
.whenAsked('Do you want to create an example page')
.respondWith(clifty_1.KEYS.ENTER)
.whenAsked('Are you using a CI/CD tool')
.respondWith(clifty_1.KEYS.DOWN, clifty_1.KEYS.ENTER) // Select No
.whenAsked('Optionally add a project-scoped MCP server configuration for the Sentry MCP?')
.respondWith(clifty_1.KEYS.ENTER) // Accept MCP config
.whenAsked('Which editor(s) do you want to configure?')
.respondWith(clifty_1.KEYS.SPACE, clifty_1.KEYS.ENTER) // Select Cursor
.expectOutput('Successfully installed the Sentry Next.js SDK!')
.run((0, utils_2.getWizardCommand)(integration));
});
(0, vitest_1.afterAll)(() => {
cleanup();
});
(0, vitest_1.test)('exits with exit code 0', () => {
(0, vitest_1.expect)(wizardExitCode).toBe(0);
});
(0, vitest_1.test)('package.json is updated correctly', () => {
(0, utils_2.checkPackageJson)(projectDir, '@sentry/nextjs');
});
(0, vitest_1.test)('.env-sentry-build-plugin is created and contains the auth token', () => {
(0, utils_1.checkEnvBuildPlugin)(projectDir);
});
(0, vitest_1.test)('example page exists', () => {
(0, utils_2.checkFileExists)(`${projectDir}/src/app/sentry-example-page/page.tsx`);
(0, utils_2.checkFileExists)(`${projectDir}/src/app/api/sentry-example-api/route.ts`);
});
(0, vitest_1.test)('config files created', () => {
(0, utils_2.checkFileExists)(`${projectDir}/sentry.server.config.ts`);
(0, utils_2.checkFileExists)(`${projectDir}/sentry.edge.config.ts`);
});
(0, vitest_1.test)('global error file exists', () => {
(0, utils_2.checkFileExists)(`${projectDir}/src/app/global-error.tsx`);
});
(0, vitest_1.test)('instrumentation files exists', () => {
(0, utils_2.checkFileExists)(`${projectDir}/src/instrumentation.ts`);
(0, utils_2.checkFileExists)(`${projectDir}/src/instrumentation-client.ts`);
});
(0, vitest_1.test)('instrumentation file contains Sentry initialization', () => {
(0, utils_2.checkFileContents)(`${projectDir}/src/instrumentation.ts`, [
'import * as Sentry from "@sentry/nextjs";',
`export async function register() {
if (process.env.NEXT_RUNTIME === "nodejs") {
await import("../sentry.server.config");
}
if (process.env.NEXT_RUNTIME === "edge") {
await import("../sentry.edge.config");
}
}
export const onRequestError = Sentry.captureRequestError;`,
]);
});
(0, vitest_1.test)('next.config file contains Sentry wrapper', () => {
(0, utils_2.checkFileContents)(`${projectDir}/next.config.ts`, [
'import { withSentryConfig } from "@sentry/nextjs"',
'export default withSentryConfig(nextConfig, {',
]);
});
(0, vitest_1.test)('runs on dev mode correctly', async () => {
await (0, utils_2.checkIfRunsOnDevMode)(projectDir, 'Ready in');
});
(0, vitest_1.test)('builds correctly', async () => {
await (0, utils_2.checkIfBuilds)(projectDir);
});
(0, vitest_1.test)('runs on prod mode correctly', async () => {
await (0, utils_2.checkIfRunsOnProdMode)(projectDir, 'Ready in');
});
(0, vitest_1.test)('MCP configuration file is created for Cursor', () => {
(0, utils_2.checkFileExists)(`${projectDir}/.cursor/mcp.json`);
(0, utils_2.checkFileContents)(`${projectDir}/.cursor/mcp.json`, [
'"mcpServers"',
'"Sentry"',
`"url": "https://mcp.sentry.dev/mcp/${utils_1.TEST_ARGS.ORG_SLUG}/${utils_1.TEST_ARGS.PROJECT_SLUG}"`,
]);
});
});
(0, vitest_1.describe)('NextJS-15 Spotlight', () => {
const integration = Constants_1.Integration.nextjs;
let wizardExitCode;
const { projectDir, cleanup } = (0, utils_1.createIsolatedTestEnv)('nextjs-15-test-app');
(0, vitest_1.beforeAll)(async () => {
wizardExitCode = await (0, clifty_1.withEnv)({
cwd: projectDir,
})
.defineInteraction()
.expectOutput('Spotlight mode enabled!')
.whenAsked('Please select your package manager.')
.respondWith(clifty_1.KEYS.DOWN, clifty_1.KEYS.ENTER) // Select yarn
.expectOutput('Installing @sentry/nextjs')
.whenAsked('Do you want to route Sentry requests in the browser through your Next.js server', {
timeout: 240000, // package installation can take a while in CI
})
.respondWith(clifty_1.KEYS.ENTER)
.whenAsked('to track the performance of your application?')
.respondWith(clifty_1.KEYS.ENTER)
.whenAsked('to get a video-like reproduction of errors during a user session?')
.respondWith(clifty_1.KEYS.ENTER)
.whenAsked('to send your application logs to Sentry?')
.respondWith(clifty_1.KEYS.ENTER)
.whenAsked('Do you want to create an example page')
.respondWith(clifty_1.KEYS.DOWN, clifty_1.KEYS.ENTER) // Skip example page
.whenAsked('Optionally add a project-scoped MCP server configuration for the Sentry MCP?')
.respondWith(clifty_1.KEYS.DOWN, clifty_1.KEYS.ENTER) // Decline MCP config
.expectOutput('Successfully installed the Sentry Next.js SDK!')
.run(`${(0, utils_2.getWizardCommand)(integration)} --spotlight`);
});
(0, vitest_1.afterAll)(() => {
cleanup();
});
(0, vitest_1.test)('exits with exit code 0', () => {
(0, vitest_1.expect)(wizardExitCode).toBe(0);
});
(0, vitest_1.test)('package.json is updated correctly', () => {
(0, utils_2.checkPackageJson)(projectDir, '@sentry/nextjs');
});
(0, vitest_1.test)('.env-sentry-build-plugin should NOT exist in spotlight mode', () => {
const envFilePath = `${projectDir}/.env.sentry-build-plugin`;
(0, utils_1.checkFileDoesNotExist)(envFilePath);
// Explicit assertion to satisfy linter
(0, vitest_1.expect)(fs.existsSync(envFilePath)).toBe(false);
});
(0, vitest_1.test)('config files created', () => {
(0, utils_2.checkFileExists)(`${projectDir}/sentry.server.config.ts`);
(0, utils_2.checkFileExists)(`${projectDir}/sentry.edge.config.ts`);
});
(0, vitest_1.test)('server config file contains empty DSN and spotlight flag', () => {
(0, utils_2.checkFileContents)(`${projectDir}/sentry.server.config.ts`, [
'dsn: ""',
'spotlight: true',
]);
});
(0, vitest_1.test)('edge config file contains empty DSN and spotlight flag', () => {
(0, utils_2.checkFileContents)(`${projectDir}/sentry.edge.config.ts`, [
'dsn: ""',
'spotlight: true',
]);
});
(0, vitest_1.test)('instrumentation client file contains empty DSN and spotlight flag', () => {
(0, utils_2.checkFileExists)(`${projectDir}/src/instrumentation-client.ts`);
(0, utils_2.checkFileContents)(`${projectDir}/src/instrumentation-client.ts`, [
'dsn: ""',
'spotlight: true',
]);
});
(0, vitest_1.test)('builds correctly', async () => {
await (0, utils_2.checkIfBuilds)(projectDir);
});
(0, vitest_1.test)('runs on dev mode correctly', async () => {
await (0, utils_2.checkIfRunsOnDevMode)(projectDir, 'Ready in');
});
});
//# sourceMappingURL=nextjs-15.test.js.map