diff --git a/src/__snapshots__/index.spec.js.snap b/src/__snapshots__/index.spec.js.snap index a0937f0..6d41920 100644 --- a/src/__snapshots__/index.spec.js.snap +++ b/src/__snapshots__/index.spec.js.snap @@ -225,3 +225,13 @@ function logAll() { } " `; + +exports[`12. Merge options - fix #12 1`] = ` +" +console.log(a); + + ↓ ↓ ↓ ↓ ↓ ↓ + +console.log(\\"unknown(1:0)\\", \\"a\\", a); +" +`; diff --git a/src/index.js b/src/index.js index f1db4f7..a849f2e 100644 --- a/src/index.js +++ b/src/index.js @@ -1,10 +1,4 @@ -const defaultSettings = { - injectScope: true, - injectVariableName: true, - injectFileName: true, -}; - -const defaultMethods = ['debug', 'error', 'exception', 'info', 'log', 'warn']; +import { buildOptions } from './utils/pluginOptions'; const idNameSelector = path => path.node.id.name; const keyNameSelector = path => path.node.key.name; @@ -35,7 +29,8 @@ export default function({ types: t }) { if (!looksLike(path.node, { name: 'console' })) { return; } - const settings = buildSettings(opts || {}); + // find somewhere we can move this so that it only needs to be called once. + const settings = buildOptions(opts || {}); const parentCallExp = path.findParent(t.isCallExpression); if (isTrackingConsoleCallStatement(path, parentCallExp, settings)) { callExpressions.add(parentCallExp); @@ -43,7 +38,7 @@ export default function({ types: t }) { }, Program: { exit(_, { file, opts }) { - const settings = buildSettings(opts || {}); + const settings = buildOptions(opts || {}); callExpressions.forEach(callExp => { if (!callExp || evaluatedExpressions.has(callExp)) { return; @@ -100,20 +95,6 @@ export default function({ types: t }) { }, []); } - function buildSettings(opts) { - // remove ignore patterns from settings since it has been consumed already - // eslint-disable-next-line no-unused-vars - const { methods, ignorePatterns, ...flags } = opts; - // output spreads the flags over each method - // in the future this could be expanded to allow method level config - return (methods || defaultMethods).reduce((acc, curr) => { - return { - ...acc, - [curr]: Object.values(flags).length ? flags : defaultSettings, - }; - }, {}); - } - function findCallScope(path, scope = []) { const parentFunc = path.findParent(path => Object.keys(scopeHandlers).includes(path.type) diff --git a/src/index.spec.js b/src/index.spec.js index 30426c4..e00902b 100644 --- a/src/index.spec.js +++ b/src/index.spec.js @@ -81,5 +81,10 @@ pluginTester({ methods: ['debug', 'log', 'info'], }, }, + { + title: 'Merge options - fix #12', + code: `console.log(a);`, + pluginOptions: { injectScope: false }, + }, ], }); diff --git a/src/utils/__snapshots__/pluginOptions.spec.js.snap b/src/utils/__snapshots__/pluginOptions.spec.js.snap new file mode 100644 index 0000000..1f1e0f7 --- /dev/null +++ b/src/utils/__snapshots__/pluginOptions.spec.js.snap @@ -0,0 +1,186 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`buildOptions should allow methods to be changed 1`] = ` +Object { + "debug": Object { + "injectFileName": true, + "injectScope": true, + "injectVariableName": true, + }, +} +`; + +exports[`buildOptions should overwrite defaults 1`] = ` +Object { + "debug": Object { + "injectFileName": false, + "injectScope": true, + "injectVariableName": true, + }, + "error": Object { + "injectFileName": false, + "injectScope": true, + "injectVariableName": true, + }, + "exception": Object { + "injectFileName": false, + "injectScope": true, + "injectVariableName": true, + }, + "info": Object { + "injectFileName": false, + "injectScope": true, + "injectVariableName": true, + }, + "log": Object { + "injectFileName": false, + "injectScope": true, + "injectVariableName": true, + }, + "warn": Object { + "injectFileName": false, + "injectScope": true, + "injectVariableName": true, + }, +} +`; + +exports[`buildOptions should return defaults for invalid args 1`] = ` +Object { + "debug": Object { + "injectFileName": true, + "injectScope": true, + "injectVariableName": true, + }, + "error": Object { + "injectFileName": true, + "injectScope": true, + "injectVariableName": true, + }, + "exception": Object { + "injectFileName": true, + "injectScope": true, + "injectVariableName": true, + }, + "info": Object { + "injectFileName": true, + "injectScope": true, + "injectVariableName": true, + }, + "log": Object { + "injectFileName": true, + "injectScope": true, + "injectVariableName": true, + }, + "warn": Object { + "injectFileName": true, + "injectScope": true, + "injectVariableName": true, + }, +} +`; + +exports[`buildOptions should return defaults for invalid args 2`] = ` +Object { + "debug": Object { + "injectFileName": true, + "injectScope": true, + "injectVariableName": true, + }, + "error": Object { + "injectFileName": true, + "injectScope": true, + "injectVariableName": true, + }, + "exception": Object { + "injectFileName": true, + "injectScope": true, + "injectVariableName": true, + }, + "info": Object { + "injectFileName": true, + "injectScope": true, + "injectVariableName": true, + }, + "log": Object { + "injectFileName": true, + "injectScope": true, + "injectVariableName": true, + }, + "warn": Object { + "injectFileName": true, + "injectScope": true, + "injectVariableName": true, + }, +} +`; + +exports[`buildOptions should return defaults for invalid args 3`] = ` +Object { + "debug": Object { + "injectFileName": true, + "injectScope": true, + "injectVariableName": true, + }, + "error": Object { + "injectFileName": true, + "injectScope": true, + "injectVariableName": true, + }, + "exception": Object { + "injectFileName": true, + "injectScope": true, + "injectVariableName": true, + }, + "info": Object { + "injectFileName": true, + "injectScope": true, + "injectVariableName": true, + }, + "log": Object { + "injectFileName": true, + "injectScope": true, + "injectVariableName": true, + }, + "warn": Object { + "injectFileName": true, + "injectScope": true, + "injectVariableName": true, + }, +} +`; + +exports[`buildOptions should return defaults for invalid args 4`] = ` +Object { + "debug": Object { + "injectFileName": true, + "injectScope": true, + "injectVariableName": true, + }, + "error": Object { + "injectFileName": true, + "injectScope": true, + "injectVariableName": true, + }, + "exception": Object { + "injectFileName": true, + "injectScope": true, + "injectVariableName": true, + }, + "info": Object { + "injectFileName": true, + "injectScope": true, + "injectVariableName": true, + }, + "log": Object { + "injectFileName": true, + "injectScope": true, + "injectVariableName": true, + }, + "warn": Object { + "injectFileName": true, + "injectScope": true, + "injectVariableName": true, + }, +} +`; diff --git a/src/utils/index.js b/src/utils/index.js new file mode 100644 index 0000000..e69de29 diff --git a/src/utils/pluginOptions.js b/src/utils/pluginOptions.js new file mode 100644 index 0000000..9fa0175 --- /dev/null +++ b/src/utils/pluginOptions.js @@ -0,0 +1,36 @@ +const defaultSettings = { + injectScope: true, + injectVariableName: true, + injectFileName: true, +}; + +const defaultMethods = ['debug', 'error', 'exception', 'info', 'log', 'warn']; + +// this should deep merge in the furture when we are dealing with more than just flags +const mergeOptions = options => { + const sanitizedOptions = Object.keys(options || {}) + .filter(key => Object.keys(defaultSettings).includes(key)) + .reduce( + (acc, key) => ({ + ...acc, + [key]: options[key], + }), + {} + ); + return Object.assign({}, defaultSettings, sanitizedOptions); +}; + +export const buildOptions = userOptions => { + // remove ignore patterns from settings since it has been consumed already + // eslint-disable-next-line no-unused-vars + const { methods, ignorePatterns, ...options } = userOptions || {}; + + // output spreads the flags over each method + // in the future this could be expanded to allow method level config + return (methods || defaultMethods).reduce((acc, method) => { + return { + ...acc, + [method]: mergeOptions(options), + }; + }, {}); +}; diff --git a/src/utils/pluginOptions.spec.js b/src/utils/pluginOptions.spec.js new file mode 100644 index 0000000..0ca9d52 --- /dev/null +++ b/src/utils/pluginOptions.spec.js @@ -0,0 +1,24 @@ +import { buildOptions } from './pluginOptions'; + +describe('buildOptions', () => { + test('should return defaults for invalid args', () => { + let actual = buildOptions(); + expect(actual).toMatchSnapshot(); + actual = buildOptions(undefined); + expect(actual).toMatchSnapshot(); + actual = buildOptions({}); + expect(actual).toMatchSnapshot(); + actual = buildOptions({ unknownFlag: false }); + expect(actual).toMatchSnapshot(); + }); + + test('should allow methods to be changed', () => { + let actual = buildOptions({ methods: ['debug'] }); + expect(actual).toMatchSnapshot(); + }); + + test('should overwrite defaults', () => { + let actual = buildOptions({ injectFileName: false }); + expect(actual).toMatchSnapshot(); + }); +});