From adc1d707444144e9acefbca6c021fad5dc9875c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leosvel=20P=C3=A9rez=20Espinosa?= Date: Mon, 3 Jun 2024 15:17:13 +0200 Subject: [PATCH] fix(linter): handle configuration without "rules" in migration (#26317) ## Current Behavior ## Expected Behavior ## Related Issue(s) Fixes #26306 --- .../migrate-no-extra-semi.spec.ts | 218 ++++++++++++++++++ .../migrate-no-extra-semi.ts | 6 +- 2 files changed, 222 insertions(+), 2 deletions(-) diff --git a/packages/eslint-plugin/src/migrations/update-19-1-0-migrate-no-extra-semi/migrate-no-extra-semi.spec.ts b/packages/eslint-plugin/src/migrations/update-19-1-0-migrate-no-extra-semi/migrate-no-extra-semi.spec.ts index a21d2b763b0b27..2f971b98349ece 100644 --- a/packages/eslint-plugin/src/migrations/update-19-1-0-migrate-no-extra-semi/migrate-no-extra-semi.spec.ts +++ b/packages/eslint-plugin/src/migrations/update-19-1-0-migrate-no-extra-semi/migrate-no-extra-semi.spec.ts @@ -76,6 +76,52 @@ describe('update-19-1-0-migrate-no-extra-semi', () => { `); }); + it('should update top level config that extends @nx/typescript and "rules" is not defined', async () => { + writeJson(tree, '.eslintrc.json', { + plugins: ['@nx'], + extends: ['@nx/typescript'], + }); + + await migrate(tree); + + expect(readJson(tree, '.eslintrc.json')).toMatchInlineSnapshot(` + { + "extends": [ + "@nx/typescript", + ], + "plugins": [ + "@nx", + ], + "rules": { + "@typescript-eslint/no-extra-semi": "error", + "no-extra-semi": "off", + }, + } + `); + + writeJson(tree, '.eslintrc.json', { + plugins: ['@nx'], + extends: ['plugin:@nx/typescript'], // alt syntax + }); + + await migrate(tree); + + expect(readJson(tree, '.eslintrc.json')).toMatchInlineSnapshot(` + { + "extends": [ + "plugin:@nx/typescript", + ], + "plugins": [ + "@nx", + ], + "rules": { + "@typescript-eslint/no-extra-semi": "error", + "no-extra-semi": "off", + }, + } + `); + }); + it('should update top level config that extends @nx/javascript', async () => { writeJson(tree, '.eslintrc.json', { plugins: ['@nx'], @@ -124,6 +170,52 @@ describe('update-19-1-0-migrate-no-extra-semi', () => { `); }); + it('should update top level config that extends @nx/javascript and "rules" is not defined', async () => { + writeJson(tree, '.eslintrc.json', { + plugins: ['@nx'], + extends: ['@nx/javascript'], + }); + + await migrate(tree); + + expect(readJson(tree, '.eslintrc.json')).toMatchInlineSnapshot(` + { + "extends": [ + "@nx/javascript", + ], + "plugins": [ + "@nx", + ], + "rules": { + "@typescript-eslint/no-extra-semi": "error", + "no-extra-semi": "off", + }, + } + `); + + writeJson(tree, '.eslintrc.json', { + plugins: ['@nx'], + extends: ['plugin:@nx/javascript'], // alt syntax + }); + + await migrate(tree); + + expect(readJson(tree, '.eslintrc.json')).toMatchInlineSnapshot(` + { + "extends": [ + "plugin:@nx/javascript", + ], + "plugins": [ + "@nx", + ], + "rules": { + "@typescript-eslint/no-extra-semi": "error", + "no-extra-semi": "off", + }, + } + `); + }); + it('should not update top level config that already defines the rules', async () => { writeJson(tree, '.eslintrc.json', { plugins: ['@nx'], @@ -263,6 +355,69 @@ describe('update-19-1-0-migrate-no-extra-semi', () => { `); }); + it('should update overrides config that extends @nx/typescript and "rules" is not defined', async () => { + writeJson(tree, 'path/to/.eslintrc.json', { + overrides: [ + { + files: ['*.ts'], + extends: ['@nx/typescript'], + }, + { + files: ['*.tsx'], + extends: ['plugin:@nx/typescript'], // alt syntax + }, + { + // Should be untouched + files: ['*.js'], + plugins: ['@nx'], + rules: {}, + }, + ], + }); + + await migrate(tree); + + expect(readJson(tree, 'path/to/.eslintrc.json')).toMatchInlineSnapshot(` + { + "overrides": [ + { + "extends": [ + "@nx/typescript", + ], + "files": [ + "*.ts", + ], + "rules": { + "@typescript-eslint/no-extra-semi": "error", + "no-extra-semi": "off", + }, + }, + { + "extends": [ + "plugin:@nx/typescript", + ], + "files": [ + "*.tsx", + ], + "rules": { + "@typescript-eslint/no-extra-semi": "error", + "no-extra-semi": "off", + }, + }, + { + "files": [ + "*.js", + ], + "plugins": [ + "@nx", + ], + "rules": {}, + }, + ], + } + `); + }); + it('should update overrides config that extends @nx/javascript', async () => { writeJson(tree, '.eslintrc.json', { overrides: [ @@ -328,6 +483,69 @@ describe('update-19-1-0-migrate-no-extra-semi', () => { `); }); + it('should update overrides config that extends @nx/javascript and "rules" is not defined', async () => { + writeJson(tree, '.eslintrc.json', { + overrides: [ + { + files: ['*.js'], + extends: ['@nx/javascript'], + }, + { + files: ['*.jsx'], + extends: ['plugin:@nx/javascript'], // alt syntax + }, + { + // Should be untouched + files: ['*.js'], + plugins: ['@nx'], + rules: {}, + }, + ], + }); + + await migrate(tree); + + expect(readJson(tree, '.eslintrc.json')).toMatchInlineSnapshot(` + { + "overrides": [ + { + "extends": [ + "@nx/javascript", + ], + "files": [ + "*.js", + ], + "rules": { + "@typescript-eslint/no-extra-semi": "error", + "no-extra-semi": "off", + }, + }, + { + "extends": [ + "plugin:@nx/javascript", + ], + "files": [ + "*.jsx", + ], + "rules": { + "@typescript-eslint/no-extra-semi": "error", + "no-extra-semi": "off", + }, + }, + { + "files": [ + "*.js", + ], + "plugins": [ + "@nx", + ], + "rules": {}, + }, + ], + } + `); + }); + it('should not update overrides config that already defines the rules', async () => { writeJson(tree, '.eslintrc.json', { overrides: [ diff --git a/packages/eslint-plugin/src/migrations/update-19-1-0-migrate-no-extra-semi/migrate-no-extra-semi.ts b/packages/eslint-plugin/src/migrations/update-19-1-0-migrate-no-extra-semi/migrate-no-extra-semi.ts index e4a8cf5ed43e98..0e4b7162a2283b 100644 --- a/packages/eslint-plugin/src/migrations/update-19-1-0-migrate-no-extra-semi/migrate-no-extra-semi.ts +++ b/packages/eslint-plugin/src/migrations/update-19-1-0-migrate-no-extra-semi/migrate-no-extra-semi.ts @@ -59,11 +59,13 @@ function addNoExtraSemiExplicitly(json: Record): boolean { ) { return wasUpdated; } - if (!json.rules['@typescript-eslint/no-extra-semi']) { + if (!json.rules?.['@typescript-eslint/no-extra-semi']) { + json.rules ??= {}; json.rules['@typescript-eslint/no-extra-semi'] = 'error'; wasUpdated = true; } - if (!json.rules['no-extra-semi']) { + if (!json.rules?.['no-extra-semi']) { + json.rules ??= {}; json.rules['no-extra-semi'] = 'off'; wasUpdated = true; }