@sentry/wizard
Version:
Sentry wizard helping you to configure your project
338 lines (314 loc) • 12.3 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
// @ts-expect-error - magicast is ESM and TS complains about that. It works though
const magicast_1 = require("magicast");
const metro_1 = require("../../src/react-native/metro");
const vitest_1 = require("vitest");
(0, vitest_1.describe)('patch metro config - sentry serializer', () => {
(0, vitest_1.describe)('patchMetroWithSentryConfigInMemory', () => {
(0, vitest_1.it)('patches react native 0.72 default metro config', async () => {
const mod = (0, magicast_1.parseModule)(`const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');
/**
* Metro configuration
* https://reactnative.dev/docs/metro
*
* @type {import('metro-config').MetroConfig}
*/
const config = {};
module.exports = mergeConfig(getDefaultConfig(__dirname), config);`);
const result = await (0, metro_1.patchMetroWithSentryConfigInMemory)(mod, async () => {
/* noop */
});
(0, vitest_1.expect)(result).toBe(true);
(0, vitest_1.expect)((0, magicast_1.generateCode)(mod.$ast).code)
.toBe(`const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');
const {
withSentryConfig
} = require("@sentry/react-native/metro");
/**
* Metro configuration
* https://reactnative.dev/docs/metro
*
* @type {import('metro-config').MetroConfig}
*/
const config = {};
module.exports = withSentryConfig(mergeConfig(getDefaultConfig(__dirname), config));`);
});
(0, vitest_1.it)('patches react native 0.65 default metro config', async () => {
const mod = (0, magicast_1.parseModule)(`/**
* Metro configuration for React Native
* https://github.com/facebook/react-native
*
* @format
*/
module.exports = {
transformer: {
getTransformOptions: async () => ({
transform: {
experimentalImportSupport: false,
inlineRequires: true,
},
}),
},
};`);
const result = await (0, metro_1.patchMetroWithSentryConfigInMemory)(mod, async () => {
/* noop */
});
(0, vitest_1.expect)(result).toBe(true);
(0, vitest_1.expect)((0, magicast_1.generateCode)(mod.$ast).code).toBe(`const {
withSentryConfig
} = require("@sentry/react-native/metro");
/**
* Metro configuration for React Native
* https://github.com/facebook/react-native
*
* @format
*/
module.exports = withSentryConfig({
transformer: {
getTransformOptions: async () => ({
transform: {
experimentalImportSupport: false,
inlineRequires: true,
},
}),
},
});`);
});
(0, vitest_1.it)('patches react native metro config exported variable', async () => {
const mod = (0, magicast_1.parseModule)(`const testConfig = {};
module.exports = testConfig;`);
const result = await (0, metro_1.patchMetroWithSentryConfigInMemory)(mod, async () => {
/* noop */
});
(0, vitest_1.expect)(result).toBe(true);
(0, vitest_1.expect)((0, magicast_1.generateCode)(mod.$ast).code).toBe(`const {
withSentryConfig
} = require("@sentry/react-native/metro");
const testConfig = {};
module.exports = withSentryConfig(testConfig);`);
});
(0, vitest_1.it)('patches custom react native metro config', async () => {
const mod = (0, magicast_1.parseModule)(`const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');
const defaultConfig = getDefaultConfig(__dirname);
const {assetExts, sourceExts} = defaultConfig.resolver;
/**
* Metro configuration
* https://facebook.github.io/metro/docs/configuration
*
* @type {import('metro-config').MetroConfig}
*/
const jsoMetroPlugin = require('obfuscator-io-metro-plugin')(
{
// for these option look javascript-obfuscator library options from above url
compact: false,
sourceMap: false,
controlFlowFlattening: true,
controlFlowFlatteningThreshold: 1,
numbersToExpressions: true,
simplify: true,
stringArrayShuffle: true,
splitStrings: true,
stringArrayThreshold: 1,
},
{
runInDev: false /* optional */,
logObfuscatedFiles: true /* optional generated files will be located at ./.jso */,
// source Map generated after obfuscation is not useful right now
sourceMapLocation:
'./index.android.bundle.map' /* optional only works if sourceMap: true in obfuscation option */,
},
);
const config = {
transformer: {
babelTransformerPath: require.resolve('react-native-svg-transformer'),
getTransformOptions: async () => ({
transform: {
experimentalImportSupport: false,
inlineRequires: true,
},
}),
},
resolver: {
assetExts: assetExts.filter(ext => ext !== 'svg'),
sourceExts: [...sourceExts, 'svg'],
},
...jsoMetroPlugin,
};
module.exports = mergeConfig(getDefaultConfig(__dirname), config);`);
const result = await (0, metro_1.patchMetroWithSentryConfigInMemory)(mod, async () => {
/* noop */
});
(0, vitest_1.expect)(result).toBe(true);
(0, vitest_1.expect)((0, magicast_1.generateCode)(mod.$ast).code)
.toBe(`const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');
const {
withSentryConfig
} = require("@sentry/react-native/metro");
const defaultConfig = getDefaultConfig(__dirname);
const {assetExts, sourceExts} = defaultConfig.resolver;
/**
* Metro configuration
* https://facebook.github.io/metro/docs/configuration
*
* @type {import('metro-config').MetroConfig}
*/
const jsoMetroPlugin = require('obfuscator-io-metro-plugin')(
{
// for these option look javascript-obfuscator library options from above url
compact: false,
sourceMap: false,
controlFlowFlattening: true,
controlFlowFlatteningThreshold: 1,
numbersToExpressions: true,
simplify: true,
stringArrayShuffle: true,
splitStrings: true,
stringArrayThreshold: 1,
},
{
runInDev: false /* optional */,
logObfuscatedFiles: true /* optional generated files will be located at ./.jso */,
// source Map generated after obfuscation is not useful right now
sourceMapLocation:
'./index.android.bundle.map' /* optional only works if sourceMap: true in obfuscation option */,
},
);
const config = {
transformer: {
babelTransformerPath: require.resolve('react-native-svg-transformer'),
getTransformOptions: async () => ({
transform: {
experimentalImportSupport: false,
inlineRequires: true,
},
}),
},
resolver: {
assetExts: assetExts.filter(ext => ext !== 'svg'),
sourceExts: [...sourceExts, 'svg'],
},
...jsoMetroPlugin,
};
module.exports = withSentryConfig(mergeConfig(getDefaultConfig(__dirname), config));`);
});
(0, vitest_1.it)('does not patch react native metro config exported as factory function', async () => {
const mod = (0, magicast_1.parseModule)(`module.exports = () => ({});`);
const result = await (0, metro_1.patchMetroWithSentryConfigInMemory)(mod, async () => {
/* noop */
});
(0, vitest_1.expect)(result).toBe(false);
(0, vitest_1.expect)((0, magicast_1.generateCode)(mod.$ast).code).toBe(`module.exports = () => ({});`);
});
});
(0, vitest_1.describe)('addSentrySerializerToMetroConfig', () => {
(0, vitest_1.it)('add to empty config', () => {
const mod = (0, magicast_1.parseModule)(`module.exports = {
other: 'config'
}`);
const configObject = getModuleExportsObject(mod);
const result = (0, metro_1.addSentrySerializerToMetroConfig)(configObject);
(0, vitest_1.expect)(result).toBe(true);
(0, vitest_1.expect)((0, magicast_1.generateCode)(mod.$ast).code).toBe(`module.exports = {
other: 'config',
serializer: {
customSerializer: createSentryMetroSerializer()
}
}`);
});
(0, vitest_1.it)('add to existing serializer config', () => {
const mod = (0, magicast_1.parseModule)(`module.exports = {
other: 'config',
serializer: {
other: 'config'
}
}`);
const configObject = getModuleExportsObject(mod);
const result = (0, metro_1.addSentrySerializerToMetroConfig)(configObject);
(0, vitest_1.expect)(result).toBe(true);
(0, vitest_1.expect)((0, magicast_1.generateCode)(mod.$ast).code).toBe(`module.exports = {
other: 'config',
serializer: {
other: 'config',
customSerializer: createSentryMetroSerializer()
}
}`);
});
(0, vitest_1.it)('not add to existing customSerializer config', () => {
const mod = (0, magicast_1.parseModule)(`module.exports = {
other: 'config',
serializer: {
other: 'config',
customSerializer: 'existing-serializer'
}
}`);
const configObject = getModuleExportsObject(mod);
const result = (0, metro_1.addSentrySerializerToMetroConfig)(configObject);
(0, vitest_1.expect)(result).toBe(false);
(0, vitest_1.expect)((0, magicast_1.generateCode)(mod.$ast).code).toBe(`module.exports = {
other: 'config',
serializer: {
other: 'config',
customSerializer: 'existing-serializer'
}
}`);
});
});
(0, vitest_1.describe)('addSentrySerializerImportToMetroConfig', () => {
(0, vitest_1.it)('add import', () => {
const mod = (0, magicast_1.parseModule)(`const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config');
module.exports = {
other: 'config'
}`);
const result = (0, metro_1.addSentrySerializerRequireToMetroConfig)(mod.$ast);
(0, vitest_1.expect)(result).toBe(true);
(0, vitest_1.expect)((0, magicast_1.generateCode)(mod.$ast).code)
.toBe(`const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config');
const {
createSentryMetroSerializer
} = require("@sentry/react-native/dist/js/tools/sentryMetroSerializer");
module.exports = {
other: 'config'
}`);
});
});
(0, vitest_1.describe)('getMetroConfigObject', () => {
(0, vitest_1.it)('get config object from variable called config', () => {
const mod = (0, magicast_1.parseModule)(`var config = { some: 'config' };`);
const configObject = (0, metro_1.getMetroConfigObject)(mod.$ast);
(0, vitest_1.expect)((configObject?.properties[0]).key
.name).toBe('some');
(0, vitest_1.expect)((configObject?.properties[0])
.value.value).toBe('config');
});
(0, vitest_1.it)('get config object from const called config', () => {
const mod = (0, magicast_1.parseModule)(`const config = { some: 'config' };`);
const configObject = (0, metro_1.getMetroConfigObject)(mod.$ast);
(0, vitest_1.expect)((configObject?.properties[0]).key
.name).toBe('some');
(0, vitest_1.expect)((configObject?.properties[0])
.value.value).toBe('config');
});
(0, vitest_1.it)('get config oject from let called config', () => {
const mod = (0, magicast_1.parseModule)(`let config = { some: 'config' };`);
const configObject = (0, metro_1.getMetroConfigObject)(mod.$ast);
(0, vitest_1.expect)((configObject?.properties[0]).key
.name).toBe('some');
(0, vitest_1.expect)((configObject?.properties[0])
.value.value).toBe('config');
});
(0, vitest_1.it)('get config object from module.exports', () => {
const mod = (0, magicast_1.parseModule)(`module.exports = { some: 'config' };`);
const configObject = (0, metro_1.getMetroConfigObject)(mod.$ast);
(0, vitest_1.expect)((configObject?.properties[0]).key
.name).toBe('some');
(0, vitest_1.expect)((configObject?.properties[0])
.value.value).toBe('config');
});
});
});
function getModuleExportsObject(mod, index = 0) {
return mod.$ast.body[index]
.expression.right;
}
//# sourceMappingURL=metro.test.js.map