UNPKG

@sentry/wizard

Version:

Sentry wizard helping you to configure your project

289 lines 12.3 kB
"use strict"; 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; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const clack_utils_1 = require("../../src/utils/clack-utils"); const fs = __importStar(require("node:fs")); const ChildProcess = __importStar(require("node:child_process")); const axios_1 = __importDefault(require("axios")); // @ts-ignore - clack is ESM and TS complains about that. It works though const clack = __importStar(require("@clack/prompts")); const Sentry = __importStar(require("@sentry/node")); jest.mock('node:child_process', () => ({ __esModule: true, ...jest.requireActual('node:child_process'), })); jest.mock('@clack/prompts', () => ({ log: { info: jest.fn(), success: jest.fn(), warn: jest.fn(), error: jest.fn(), }, outro: jest.fn(), text: jest.fn(), confirm: jest.fn(), cancel: jest.fn(), // passthrough for abortIfCancelled isCancel: jest.fn().mockReturnValue(false), spinner: jest .fn() .mockImplementation(() => ({ start: jest.fn(), stop: jest.fn() })), })); const clackMock = clack; jest.mock('axios'); const mockedAxios = axios_1.default; jest.mock('opn', () => jest.fn(() => Promise.resolve({ on: jest.fn() }))); function mockUserResponse(fn, response) { fn.mockReturnValueOnce(response); } describe('askForToolConfigPath', () => { afterEach(() => { jest.clearAllMocks(); }); it('returns undefined if users have no config file', async () => { mockUserResponse(clack.confirm, false); const result = await (0, clack_utils_1.askForToolConfigPath)('Webpack', 'webpack.config.js'); expect(clack.confirm).toHaveBeenCalledWith(expect.objectContaining({ message: expect.stringContaining('have a Webpack config file'), })); expect(result).toBeUndefined(); }); it('returns the path if users have a config file and the entered path is valid', async () => { mockUserResponse(clack.confirm, true); mockUserResponse(clack.text, 'my.webpack.config.js'); const result = await (0, clack_utils_1.askForToolConfigPath)('Webpack', 'webpack.config.js'); expect(clack.confirm).toHaveBeenCalledWith(expect.objectContaining({ message: expect.stringContaining('have a Webpack config file'), })); expect(clack.text).toHaveBeenCalledWith(expect.objectContaining({ message: expect.stringContaining('enter the path to your Webpack config file'), })); expect(result).toBe('my.webpack.config.js'); }); }); describe('createNewConfigFile', () => { afterEach(() => { jest.clearAllMocks(); }); it('writes the file to disk and returns true if the file was created successfully', async () => { const writeFileSpy = jest .spyOn(fs.promises, 'writeFile') .mockImplementation(jest.fn()); const filename = '/webpack.config.js'; const code = 'module.exports = {/*config...*/}'; const result = await (0, clack_utils_1.createNewConfigFile)(filename, code); expect(result).toBe(true); expect(writeFileSpy).toHaveBeenCalledWith(filename, code); }); it('logs more information if provided as an argument', async () => { jest.spyOn(fs.promises, 'writeFile').mockImplementation(jest.fn()); const filename = '/webpack.config.js'; const code = 'module.exports = {/*config...*/}'; const moreInfo = 'More information...'; await (0, clack_utils_1.createNewConfigFile)(filename, code, moreInfo); expect(clack.log.info).toHaveBeenCalledTimes(1); expect(clack.log.info).toHaveBeenCalledWith(expect.stringContaining(moreInfo)); }); it('returns false and logs a warning if the file could not be created', async () => { const writeFileSpy = jest .spyOn(fs.promises, 'writeFile') .mockImplementation(() => Promise.reject(new Error('Could not write'))); const filename = '/webpack.config.js'; const code = 'module.exports = {/*config...*/}'; const result = await (0, clack_utils_1.createNewConfigFile)(filename, code); expect(result).toBe(false); expect(writeFileSpy).toHaveBeenCalledWith(filename, code); expect(clack.log.warn).toHaveBeenCalledTimes(1); }); it('returns false if the passed path is not absolute', async () => { const result = await (0, clack_utils_1.createNewConfigFile)('./relative/webpack.config.js', ''); expect(result).toBe(false); }); }); describe('installPackage', () => { afterEach(() => { jest.clearAllMocks(); }); it('force-installs a package if the forceInstall flag is set', async () => { const packageManagerMock = { name: 'npm', label: 'NPM', installCommand: 'npm install', buildCommand: 'npm run build', runScriptCommand: 'npm run', flags: '', forceInstallFlag: '--force', detect: jest.fn(), addOverride: jest.fn(), }; const execSpy = jest .spyOn(ChildProcess, 'exec') // @ts-expect-error - don't care about the return value .mockImplementationOnce((cmd, cb) => { if (cb) { // @ts-expect-error - don't care about the options value cb(null, '', ''); } }); await (0, clack_utils_1.installPackage)({ alreadyInstalled: false, packageName: '@sentry/sveltekit', packageNameDisplayLabel: '@sentry/sveltekit', forceInstall: true, askBeforeUpdating: false, packageManager: packageManagerMock, }); expect(execSpy).toHaveBeenCalledWith('npm install @sentry/sveltekit --force', expect.any(Function)); }); it.each([false, undefined])("doesn't force-install a package if the forceInstall flag is %s", async (flag) => { const packageManagerMock = { name: 'npm', label: 'NPM', installCommand: 'npm install', buildCommand: 'npm run build', runScriptCommand: 'npm run', flags: '', forceInstallFlag: '--force', detect: jest.fn(), addOverride: jest.fn(), }; const execSpy = jest .spyOn(ChildProcess, 'exec') // @ts-expect-error - don't care about the return value .mockImplementationOnce((cmd, cb) => { if (cb) { // @ts-expect-error - don't care about the options value cb(null, '', ''); } }); await (0, clack_utils_1.installPackage)({ alreadyInstalled: false, packageName: '@sentry/sveltekit', packageNameDisplayLabel: '@sentry/sveltekit', forceInstall: flag, askBeforeUpdating: false, packageManager: packageManagerMock, }); expect(execSpy).toHaveBeenCalledWith('npm install @sentry/sveltekit ', expect.any(Function)); }); }); describe('askForWizardLogin', () => { // mock axios afterEach(() => { // clackMock.confirm.mockClear(); // mockUserResponse(clack.confirm as jest.Mock, undefined); }); beforeEach(() => { jest.clearAllMocks(); mockedAxios.get.mockClear(); clackMock.confirm.mockClear(); clackMock.confirm.mockReset(); mockUserResponse(clack.confirm, undefined); }); it('asks if a user already has a Sentry account by default', async () => { mockUserResponse(clack.confirm, Promise.resolve(true)); // Provide the data object to be returned mockedAxios.get.mockResolvedValue({ data: { hash: 'mockedHash', }, }); await (0, clack_utils_1.askForWizardLogin)({ url: 'https://santry.io/' }); expect(clack.confirm).toHaveBeenCalledWith(expect.objectContaining({ message: expect.stringContaining('already have a Sentry account'), })); }); it('skips asking for if a user already has a Sentry account if org and project are pre-selected', async () => { mockUserResponse(clackMock.confirm, Promise.resolve(true)); // Provide the data object to be returned mockedAxios.get.mockResolvedValue({ data: { hash: 'mockedHash', }, }); await (0, clack_utils_1.askForWizardLogin)({ url: 'https://santry.io/', orgSlug: 'my-org', projectSlug: 'my-project', }); expect(clack.confirm).not.toHaveBeenCalled(); }); }); describe('abort', () => { const sentryTxn = { setStatus: jest.fn(), finish: jest.fn(), }; let sentrySession = { status: 999, }; beforeEach(() => { jest.clearAllMocks(); sentrySession = { status: 999, }; }); jest.spyOn(Sentry, 'getCurrentHub').mockReturnValue({ getScope: () => ({ // @ts-expect-error - don't care about the rest of the required props value getTransaction: () => sentryTxn, // @ts-expect-error - don't care about the rest of the required props value getSession: () => sentrySession, }), captureSession: jest.fn(), }); const flushSpy = jest.fn(); jest.spyOn(Sentry, 'flush').mockImplementation(flushSpy); it('ends the process with an error exit code by default', async () => { // @ts-ignore - jest doesn't like the empty function // eslint-disable-next-line @typescript-eslint/no-empty-function const exitSpy = jest.spyOn(process, 'exit').mockImplementation(() => { }); await (0, clack_utils_1.abort)(); expect(exitSpy).toHaveBeenCalledWith(1); expect(clackMock.outro).toHaveBeenCalledTimes(1); expect(clackMock.outro).toHaveBeenCalledWith('Wizard setup cancelled.'); expect(sentryTxn.setStatus).toHaveBeenLastCalledWith('aborted'); expect(sentryTxn.finish).toHaveBeenCalledTimes(1); expect(sentrySession.status).toBe('crashed'); expect(flushSpy).toHaveBeenLastCalledWith(3000); }); it('ends the process with a custom exit code and message if provided', async () => { // @ts-ignore - jest doesn't like the empty function // eslint-disable-next-line @typescript-eslint/no-empty-function const exitSpy = jest.spyOn(process, 'exit').mockImplementation(() => { }); await (0, clack_utils_1.abort)('Bye', 0); expect(exitSpy).toHaveBeenCalledWith(0); expect(clackMock.outro).toHaveBeenCalledTimes(1); expect(clackMock.outro).toHaveBeenCalledWith('Bye'); expect(sentryTxn.setStatus).toHaveBeenLastCalledWith('cancelled'); expect(sentryTxn.finish).toHaveBeenCalledTimes(1); expect(sentrySession.status).toBe('abnormal'); expect(flushSpy).toHaveBeenLastCalledWith(3000); }); }); //# sourceMappingURL=clack-utils.test.js.map