@sentry/wizard
Version:
Sentry wizard helping you to configure your project
208 lines • 10.6 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 Constants_1 = require("../../lib/Constants");
const utils_1 = require("../utils");
const path = __importStar(require("path"));
const utils_2 = require("../utils");
const vitest_1 = require("vitest");
vitest_1.describe.sequential('Angular-17', () => {
(0, vitest_1.describe)('with empty project', () => {
const integration = Constants_1.Integration.angular;
const projectDir = path.resolve(__dirname, '../test-applications/angular-17-test-app');
(0, vitest_1.beforeAll)(async () => {
(0, utils_1.revertLocalChanges)(projectDir);
await runWizardOnAngularProject(projectDir, integration);
});
(0, vitest_1.afterAll)(() => {
(0, utils_1.revertLocalChanges)(projectDir);
(0, utils_1.cleanupGit)(projectDir);
});
checkAngularProject(projectDir, integration);
});
(0, vitest_1.describe)('with pre-defined ErrorHandler', () => {
const integration = Constants_1.Integration.angular;
const projectDir = path.resolve(__dirname, '../test-applications/angular-17-test-app');
(0, vitest_1.beforeAll)(async () => {
(0, utils_1.revertLocalChanges)(projectDir);
await runWizardOnAngularProject(projectDir, integration, (projectDir) => {
(0, utils_1.modifyFile)(`${projectDir}/src/app/app.config.ts`, {
'providers: [': `providers: [{
provide: ErrorHandler,
useValue: null
},
`,
});
});
});
(0, vitest_1.afterAll)(() => {
(0, utils_1.revertLocalChanges)(projectDir);
(0, utils_1.cleanupGit)(projectDir);
});
checkAngularProject(projectDir, integration, {
preExistingErrorHandler: true,
});
});
});
async function runWizardOnAngularProject(projectDir, integration, fileModificationFn) {
const wizardInstance = (0, utils_1.startWizardInstance)(integration, projectDir, true);
if (fileModificationFn) {
fileModificationFn(projectDir);
await wizardInstance.waitForOutput('Do you want to continue anyway?');
await wizardInstance.sendStdinAndWaitForOutput([utils_1.KEYS.ENTER], 'Please select your package manager.');
}
else {
await wizardInstance.waitForOutput('Please select your package manager.');
}
await wizardInstance.sendStdinAndWaitForOutput(
// Selecting `yarn v1` as the package manager
[utils_1.KEYS.DOWN, utils_1.KEYS.ENTER],
// "Do you want to enable Tracing", sometimes doesn't work as `Tracing` can be printed in bold.
'to track the performance of your application?', {
timeout: 240000,
optional: true,
});
await wizardInstance.sendStdinAndWaitForOutput(
// select "Yes" for tracing
[utils_1.KEYS.ENTER],
// "Do you want to enable Sentry Session Replay", sometimes doesn't work as `Sentry Session Replay` can be printed in bold.
'to get a video-like reproduction of errors during a user session?');
await wizardInstance.sendStdinAndWaitForOutput(
// select "Yes" for replay
[utils_1.KEYS.ENTER],
// "Do you want to enable Logs", sometimes doesn't work as `Logs` can be printed in bold.
'to send your application logs to Sentry?');
await wizardInstance.sendStdinAndWaitForOutput(
// select "Yes" for logs
[utils_1.KEYS.ENTER], 'Where are your build artifacts located?', {
timeout: 240000, // installing Sentry CLI can take a while
});
const sourcemapsConfiguredPromise = wizardInstance.waitForOutput('Added a sentry:sourcemaps script to your package.json');
const buildScriptPromptedPromise = wizardInstance.waitForOutput('Do you want to automatically run the sentry:sourcemaps script after each production build?');
const optionalArtifactsNotFoundPromise = wizardInstance.waitForOutput("We couldn't find build artifacts at", {
optional: true,
timeout: 5000,
});
// ./dist is the default value, no need to change it
wizardInstance.sendStdin(utils_1.KEYS.ENTER);
const optionalArtifactsNotFoundPrompted = await optionalArtifactsNotFoundPromise;
if (optionalArtifactsNotFoundPrompted) {
// The wizard now presents options when artifacts aren't found:
// - "Let the wizard run the build command"
// - "Enter a different path manually"
// - "Proceed anyway — I believe the path is correct"
// We want to select "Proceed anyway" (third option)
wizardInstance.sendStdin(utils_1.KEYS.DOWN);
wizardInstance.sendStdin(utils_1.KEYS.DOWN);
wizardInstance.sendStdin(utils_1.KEYS.ENTER);
}
await sourcemapsConfiguredPromise;
await buildScriptPromptedPromise;
await wizardInstance.sendStdinAndWaitForOutput([utils_1.KEYS.ENTER], // yes, automatically add sentry:sourcemaps script
'Is yarn build your production build command?');
await wizardInstance.sendStdinAndWaitForOutput([utils_1.KEYS.ENTER], // yes, yarn build is the production build command
'Are you using a CI/CD tool to build and deploy your application?');
await wizardInstance.sendStdinAndWaitForOutput([utils_1.KEYS.DOWN, utils_1.KEYS.ENTER], // no CI/CD tool
'Do you want to create an example component to test your Sentry setup?');
await wizardInstance.sendStdinAndWaitForOutput([utils_1.KEYS.ENTER], // yes, create example component
'Did you apply the snippet above?');
await wizardInstance.sendStdinAndWaitForOutput([utils_1.KEYS.ENTER], // yes, applied the snippet
'Looks like you have Prettier in your project. Do you want to run it on your files?');
await wizardInstance.sendStdinAndWaitForOutput([utils_1.KEYS.ENTER], // yes, run prettier
'Successfully installed the Sentry Angular SDK!');
wizardInstance.kill();
}
function checkAngularProject(projectDir, integration, options) {
(0, vitest_1.test)('package.json is updated correctly', () => {
(0, utils_1.checkPackageJson)(projectDir, integration);
const packageJsonFile = path.resolve(projectDir, 'package.json');
(0, utils_1.checkFileContents)(packageJsonFile, [
`"sentry:sourcemaps": "sentry-cli sourcemaps inject --org ${utils_2.TEST_ARGS.ORG_SLUG} --project ${utils_2.TEST_ARGS.PROJECT_SLUG} ./dist && sentry-cli sourcemaps upload --org ${utils_2.TEST_ARGS.ORG_SLUG} --project ${utils_2.TEST_ARGS.PROJECT_SLUG} ./dist"`,
`"build": "ng build && yarn sentry:sourcemaps"`,
]);
});
(0, vitest_1.test)('Sentry is correctly injected into Angular app config', () => {
const appConfigFile = path.resolve(projectDir, 'src/main.ts');
(0, utils_1.checkFileExists)(appConfigFile);
(0, utils_1.checkFileContents)(appConfigFile, [
`import * as Sentry from '@sentry/angular'`,
'Sentry.init({',
utils_2.TEST_ARGS.PROJECT_DSN,
'Sentry.browserTracingIntegration()',
'Sentry.replayIntegration()',
'tracesSampleRate: 1',
'replaysSessionSampleRate: 0.1',
'replaysOnErrorSampleRate: 1',
'enableLogs: true',
]);
});
(0, vitest_1.test)('Sentry is correctly injected into Angular app module', () => {
const appModuleFile = path.resolve(projectDir, 'src/app/app.config.ts');
(0, utils_1.checkFileExists)(appModuleFile);
// Checking if the ErrorHandler is already present in the providers array,
// and if it is, we skip adding it
if (options?.preExistingErrorHandler) {
(0, utils_1.checkFileDoesNotContain)(appModuleFile, 'Sentry.createErrorHandler()');
}
(0, utils_1.checkFileContents)(appModuleFile, [
`import * as Sentry from '@sentry/angular'`,
options?.preExistingErrorHandler
? `provide: ErrorHandler,
useValue: null`
: `provide: ErrorHandler,
useValue: Sentry.createErrorHandler()`,
`provide: Sentry.TraceService,
deps: [Router]`,
`provide: APP_INITIALIZER,
useFactory: () => () => {},
deps: [Sentry.TraceService],
multi: true`,
]);
});
(0, vitest_1.test)('angular.json is updated correctly', async () => {
const angularJsonFile = path.resolve(projectDir, 'angular.json');
(0, utils_1.checkFileExists)(angularJsonFile);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const angularJson = (await import(angularJsonFile));
// eslint-disable-next-line @typescript-eslint/no-explicit-any
for (const [, project] of Object.entries(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
angularJson.projects)) {
(0, vitest_1.expect)(
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
project?.architect?.build?.configurations?.production?.sourceMap).toBe(true);
}
});
(0, vitest_1.test)('builds successfully', async () => {
await (0, utils_1.checkIfBuilds)(projectDir);
});
(0, vitest_1.test)('runs on prod mode correctly', async () => {
await (0, utils_1.checkIfRunsOnProdMode)(projectDir, 'Application bundle generation complete.');
});
(0, vitest_1.test)('runs on dev mode correctly', async () => {
await (0, utils_1.checkIfRunsOnDevMode)(projectDir, 'Application bundle generation complete.');
});
}
//# sourceMappingURL=angular-17.test.js.map