From e21e0b6f0aaf58da8d4b60b85fff4856250d2faa Mon Sep 17 00:00:00 2001 From: Jordan Welch Date: Sun, 20 Oct 2024 15:01:57 -0500 Subject: [PATCH 1/2] update Eslint config --- eslint.config.mjs | 50 +++++++++++++++++++++++++++++++++++++++++++++++ package.json | 23 +++------------------- 2 files changed, 53 insertions(+), 20 deletions(-) create mode 100644 eslint.config.mjs diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000..8c4aea0 --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,50 @@ +import globals from 'globals'; +import pluginJs from '@eslint/js'; +import stylisticJs from '@stylistic/eslint-plugin-js'; + +export default [ + {files: ['**/*.js'], languageOptions: {sourceType: 'commonjs'}}, + {languageOptions: { globals: globals.browser }}, + pluginJs.configs.recommended, + { + languageOptions: { + globals: { + ...globals.jest, + Log: 'readonly', + nunjucks: 'writable', + translate: 'writable', + }, + }, + plugins: { + '@stylistic': stylisticJs, + }, + rules: { + // Stylistic rules + '@stylistic/comma-dangle': ['error', 'always-multiline'], + '@stylistic/indent': ['error', 2], + '@stylistic/max-len': ['error', { + ignoreStrings: true, + ignoreTrailingComments: true, + ignoreUrls: true, + tabWidth: 2, + }], + '@stylistic/no-multi-spaces': 'error', + '@stylistic/no-multiple-empty-lines': ['error', { max: 1 }], + '@stylistic/quote-props': ['error', 'as-needed'], + '@stylistic/quotes': ['error', 'single', { + avoidEscape: true, + }], + '@stylistic/semi': ['error', 'always'], + '@stylistic/space-before-function-paren': ['error', 'always'], + + // ESLint rules + 'no-console': ['error', { + allow: ['warn', 'error'], + }], + 'no-unused-vars': ['error', { + argsIgnorePattern: '^_', + caughtErrorsIgnorePattern: '^_', + }], + }, + }, +]; diff --git a/package.json b/package.json index 129a31a..2d5aa49 100644 --- a/package.json +++ b/package.json @@ -15,9 +15,9 @@ "node": ">=20.0.0" }, "devDependencies": { - "eslint": "^8.43.0", - "eslint-config-airbnb-base": "^15.0.0", - "eslint-plugin-import": "^2.27.5", + "@eslint/js": "^9.13.0", + "@stylistic/eslint-plugin-js": "^2.9.0", + "eslint": "^9.13.0", "fetch-mock": "^11.1.5", "jest": "^29.5.0", "nunjucks": "^3.2.4" @@ -32,22 +32,5 @@ "repository": { "type": "git", "url": "git+https://github.com/JHWelch/MMM-CTA.git" - }, - "eslintConfig": { - "env": { - "browser": true, - "commonjs": true, - "es2021": true - }, - "extends": "airbnb-base", - "overrides": [], - "parserOptions": { - "ecmaVersion": "latest" - }, - "rules": { - "no-undef": "off", - "no-underscore-dangle": "off", - "import/no-unresolved": "off" - } } } From 02b334983662e0416eff9a026fe02428619028fc Mon Sep 17 00:00:00 2001 From: Jordan Welch Date: Sun, 20 Oct 2024 15:08:40 -0500 Subject: [PATCH 2/2] Lint codebase --- MMM-CTA.js | 44 +++++++++++++++++------------------ __mocks__/Module.js | 36 ++++++++++++++-------------- __mocks__/node_helper.js | 16 ++++++------- __tests__/MMM-CTA.spec.js | 13 ++++------- __tests__/node_helper.spec.js | 3 --- node_helper.js | 32 +++++++++++++++---------- 6 files changed, 73 insertions(+), 71 deletions(-) diff --git a/MMM-CTA.js b/MMM-CTA.js index 6c7845b..cdb0215 100644 --- a/MMM-CTA.js +++ b/MMM-CTA.js @@ -24,7 +24,7 @@ Module.register('MMM-CTA', { loading: true, - start() { + start () { Log.info(`Starting module: ${this.name}`); const self = this; @@ -35,7 +35,7 @@ Module.register('MMM-CTA', { }, this.config.updateInterval); }, - getData() { + getData () { this.sendSocketNotification('MMM-CTA-FETCH', { trainApiKey: this.config.trainApiKey, busApiKey: this.config.busApiKey, @@ -45,11 +45,11 @@ Module.register('MMM-CTA', { }); }, - getTemplate() { + getTemplate () { return 'templates/MMM-CTA.njk'; }, - getTemplateData() { + getTemplateData () { return { loading: this.loading, routeIcons: this.config.routeIcons, @@ -67,25 +67,25 @@ Module.register('MMM-CTA', { }; }, - getScripts() { + getScripts () { return []; }, - getStyles() { + getStyles () { return [ 'font-awesome.css', 'MMM-CTA.css', ]; }, - getTranslations() { + getTranslations () { return { en: 'translations/en.json', es: 'translations/es.json', }; }, - socketNotificationReceived(notification, payload) { + socketNotificationReceived (notification, payload) { if (notification !== 'MMM-CTA-DATA') { return; } @@ -95,7 +95,7 @@ Module.register('MMM-CTA', { this.updateDom(300); }, - getMinutesUntil(arrivalTime) { + getMinutesUntil (arrivalTime) { const now = new Date(); const diffInMilliseconds = new Date(arrivalTime) - now; const diffInMinutes = Math.floor(diffInMilliseconds / 1000 / 60); @@ -103,7 +103,7 @@ Module.register('MMM-CTA', { return this.formatMinutes(diffInMinutes); }, - formatMinutes(minutes) { + formatMinutes (minutes) { const minutesInt = parseInt(minutes, 10); if (Number.isNaN(minutesInt)) { @@ -115,19 +115,19 @@ Module.register('MMM-CTA', { return this.minutesWithSuffix(minutesInt); }, - minutesWithSuffix(minutes) { + minutesWithSuffix (minutes) { switch (this.config.suffixStyle) { - case 'none': - return minutes.toString(); - case 'short': - return `${minutes.toString()}m`; - case 'long': - default: - if (minutes === 1) { - return `${minutes.toString()} min`; - } - - return `${minutes.toString()} mins`; + case 'none': + return minutes.toString(); + case 'short': + return `${minutes.toString()}m`; + case 'long': + default: + if (minutes === 1) { + return `${minutes.toString()} min`; + } + + return `${minutes.toString()} mins`; } }, }); diff --git a/__mocks__/Module.js b/__mocks__/Module.js index 19b7616..e4e089b 100644 --- a/__mocks__/Module.js +++ b/__mocks__/Module.js @@ -1,12 +1,12 @@ -/* eslint-disable no-param-reassign */ + global.Module = { definitions: {}, - create(name) { + create (name) { return this.definitions[name]; }, - register(name, overrides) { + register (name, overrides) { const base = { requiresVersion: '2.0.0', @@ -18,33 +18,33 @@ global.Module = { _nunjucksEnvironment: { addFilter: jest.fn() }, - init() { + init () { Log.log(this.defaults); }, - start() { + start () { Log.info(`Starting module: ${this.name}`); }, - getScripts() { + getScripts () { return []; }, - getStyles() { + getStyles () { return []; }, - getTranslations() { + getTranslations () { return false; }, getDom: jest.fn(), - getHeader() { + getHeader () { return this.data.header; }, - getTemplate() { + getTemplate () { return ( `
${ this.name @@ -54,11 +54,11 @@ global.Module = { ); }, - getTemplateData() { + getTemplateData () { return {}; }, - notificationReceived(notification, payload, sender) { + notificationReceived (notification, payload, sender) { if (sender) { Log.log( `${this.name @@ -74,11 +74,11 @@ global.Module = { } }, - nunjucksEnvironment() { + nunjucksEnvironment () { return this._nunjucksEnvironment; }, - socketNotificationReceived(notification, payload) { + socketNotificationReceived (notification, payload) { Log.log( `${this.name } received a socket notification: ${ @@ -88,15 +88,15 @@ global.Module = { ); }, - suspend() { + suspend () { Log.log(`${this.name} is suspended.`); }, - resume() { + resume () { Log.log(`${this.name} is resumed.`); }, - setData(data) { + setData (data) { this.data = data; this.name = data.name; this.identifier = data.identifier; @@ -105,7 +105,7 @@ global.Module = { this.setConfig(data.config, data.configDeepMerge); }, - setConfig(config) { + setConfig (config) { this.config = { ...this.defaults, ...config }; }, diff --git a/__mocks__/node_helper.js b/__mocks__/node_helper.js index e9253f8..609726b 100644 --- a/__mocks__/node_helper.js +++ b/__mocks__/node_helper.js @@ -1,24 +1,24 @@ /* eslint-disable no-unused-vars */ module.exports = { - create(overrides) { + create (overrides) { const base = { - init() {}, + init () {}, - loaded(callback) { + loaded (callback) { callback(); }, - start() {}, + start () {}, - stop() {}, + stop () {}, - socketNotificationReceived(notification, payload) {}, + socketNotificationReceived (notification, payload) {}, - setName(name) { + setName (name) { this.name = name; }, - setPath(path) { + setPath (path) { this.path = path; }, diff --git a/__tests__/MMM-CTA.spec.js b/__tests__/MMM-CTA.spec.js index a1f97a3..c0a0821 100644 --- a/__tests__/MMM-CTA.spec.js +++ b/__tests__/MMM-CTA.spec.js @@ -1,8 +1,5 @@ -/* eslint-disable global-require */ -beforeAll(() => { - require('../__mocks__/Module'); - require('../__mocks__/globalLogger'); -}); +require('../__mocks__/Module'); +require('../__mocks__/globalLogger'); const name = 'MMM-CTA'; @@ -176,11 +173,11 @@ describe('getTemplateData', () => { describe('train information', () => { beforeEach(() => { - now = new Date(); + const now = new Date(); jest.useFakeTimers().setSystemTime(now); // Ensures time is consistent - threeMinutes = new Date(); + const threeMinutes = new Date(); threeMinutes.setMinutes(threeMinutes.getMinutes() + 1); - twelveMinutes = new Date(); + const twelveMinutes = new Date(); twelveMinutes.setMinutes(twelveMinutes.getMinutes() + 12); stops = [{ diff --git a/__tests__/node_helper.spec.js b/__tests__/node_helper.spec.js index add6186..64f5af4 100644 --- a/__tests__/node_helper.spec.js +++ b/__tests__/node_helper.spec.js @@ -1,6 +1,5 @@ const { default: fetchMock } = require('fetch-mock'); -/* eslint-disable global-require */ beforeAll(() => { require('../__mocks__/logger'); }); @@ -131,8 +130,6 @@ let fetch; beforeEach(() => { helper = require('../node_helper'); - Log = require('logger'); // eslint-disable-line import/no-unresolved - helper.setName('MMM-CTA'); }); diff --git a/node_helper.js b/node_helper.js index 61190eb..c883f41 100644 --- a/node_helper.js +++ b/node_helper.js @@ -9,7 +9,7 @@ const Log = require('logger'); const NodeHelper = require('node_helper'); module.exports = NodeHelper.create({ - socketNotificationReceived(notification, payload) { + socketNotificationReceived (notification, payload) { if (notification !== 'MMM-CTA-FETCH') { return; } @@ -20,7 +20,7 @@ module.exports = NodeHelper.create({ this.getData(payload); }, - async getData({ + async getData ({ trainApiKey, busApiKey, maxResultsTrain, @@ -32,14 +32,22 @@ module.exports = NodeHelper.create({ return { type: 'train', name: stop.name, - arrivals: await this.getTrainData(stop.id, maxResultsTrain, trainApiKey), + arrivals: await this.getTrainData( + stop.id, + maxResultsTrain, + trainApiKey, + ), }; } return { type: 'bus', name: stop.name, - arrivals: await this.getBusData(stop.id, maxResultsBus, busApiKey), + arrivals: await this.getBusData( + stop.id, + maxResultsBus, + busApiKey, + ), }; })); @@ -48,7 +56,7 @@ module.exports = NodeHelper.create({ }); }, - async getBusData(id, maxResults, apiKey) { + async getBusData (id, maxResults, apiKey) { const response = await fetch(this.busUrl(id, maxResults, apiKey)); const { 'bustime-response': data } = await response.json(); @@ -63,7 +71,7 @@ module.exports = NodeHelper.create({ })); }, - async getTrainData(id, maxResults, apiKey) { + async getTrainData (id, maxResults, apiKey) { const response = await fetch(this.trainUrl(id, maxResults, apiKey)); const { ctatt: data } = await response.json(); @@ -78,13 +86,13 @@ module.exports = NodeHelper.create({ })); }, - validate(payload) { + validate (payload) { const required = [/** TODO: Add Required */]; return this.validateRequired(payload, required); }, - validateRequired(payload, required) { + validateRequired (payload, required) { let valid = true; required.forEach((req) => { if (!payload[req]) { @@ -96,19 +104,19 @@ module.exports = NodeHelper.create({ return valid; }, - busUrl(id, maxResults, apiKey) { + busUrl (id, maxResults, apiKey) { const baseUrl = 'http://www.ctabustracker.com/bustime/api/v2/getpredictions'; return `${baseUrl}?key=${apiKey}&stpid=${id}&top=${maxResults}&format=json`; }, - trainUrl(id, maxResults, apiKey) { + trainUrl (id, maxResults, apiKey) { const baseUrl = 'http://lapi.transitchicago.com/api/1.0/ttarrivals.aspx'; - return `${baseUrl}?key=${apiKey}&mapid=${id}&max=${maxResults}&outputType=json`; + return `${baseUrl}?key=${apiKey}&mapid=${id}&max=${maxResults}&outputType=json`; // eslint-disable-line @stylistic/max-len }, - routeToColor(route) { + routeToColor (route) { return { Red: 'red', Blue: 'blue',