diff --git a/eslint-plugin-expensify/CONST.js b/eslint-plugin-expensify/CONST.js index abfc6dc..99d9b5b 100644 --- a/eslint-plugin-expensify/CONST.js +++ b/eslint-plugin-expensify/CONST.js @@ -27,5 +27,6 @@ module.exports = { ONYX_ONE_PARAM: 'The withOnyx HOC must be passed at least one argument.', MUST_USE_VARIABLE_FOR_ASSIGNMENT: '{{key}} must be assigned as a variable instead of direct assignment.', NO_DEFAULT_PROPS: 'defaultProps should not be used in function components. Use default Arguments instead.', + USE_PERIODS_ERROR_MESSAGES: 'Use periods at the end of error messages.' }, }; diff --git a/eslint-plugin-expensify/tests/use-periods-error-messages.test.js b/eslint-plugin-expensify/tests/use-periods-error-messages.test.js new file mode 100644 index 0000000..c0c3c4b --- /dev/null +++ b/eslint-plugin-expensify/tests/use-periods-error-messages.test.js @@ -0,0 +1,38 @@ +const RuleTester = require('eslint').RuleTester; +const rule = require('../use-periods-for-error-messages'); +const message = require('../CONST').MESSAGE.USE_PERIODS_ERROR_MESSAGES; + +const ruleTester = new RuleTester({ + parserOptions: { + ecmaVersion: 6, + sourceType: 'module', + }, +}); + +const goodExample = ` +error: { + testMessage: 'This is a test message.' +} +`; + +const badExample = ` +error: { + testMessage: 'This is a test message' +} +`; + +ruleTester.run('use-periods-for-error-messages', rule, { + valid: [ + { + code: goodExample, + }, + ], + invalid: [ + { + code: badExample, + errors: [{ + message, + }], + }, + ], +}); diff --git a/eslint-plugin-expensify/use-periods-for-error-messages.js b/eslint-plugin-expensify/use-periods-for-error-messages.js new file mode 100644 index 0000000..3875aa9 --- /dev/null +++ b/eslint-plugin-expensify/use-periods-for-error-messages.js @@ -0,0 +1,31 @@ +require('lodash/get'); +const message = require('./CONST').MESSAGE.USE_PERIODS_ERROR_MESSAGES; + +module.exports = { + create(context) { + return { + Property(node) { + if (!node.key || node.key.name !== 'error' || !node.value || node.value.type !== 'ObjectExpression') { + return; + } + node.value.properties.forEach((property) => { + if (!property.value || property.value.type !== 'Literal' || typeof property.value.value !== 'string') { + return; + } + const errorMessage = property.value.value; + if (!errorMessage.endsWith('.')) { + context.report({ + node: property, + message, + fix: function (fixer) { + const lastChar = errorMessage[errorMessage.length - 1]; + const fixedMessage = lastChar === '.' ? errorMessage : `${errorMessage}.`; + return fixer.replaceText(property.value, `'${fixedMessage}'`); + } + }); + } + }); + }, + }; + }, +}; diff --git a/package.json b/package.json index 767afa5..0af025b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "eslint-config-expensify", - "version": "2.0.44", + "version": "2.0.45", "description": "Expensify's ESLint configuration following our style guide", "main": "index.js", "repository": {