diff --git a/package-lock.json b/package-lock.json index 8ce6cd2..9b93d09 100644 --- a/package-lock.json +++ b/package-lock.json @@ -36,7 +36,6 @@ "prettier": "^3.2.4", "prettier-plugin-packagejson": "^2.4.9", "rimraf": "^5.0.5", - "tap-mocha-reporter": "^5.0.4", "tsx": "^4.7.0", "typescript": "^5.3.3", "vsce": "^2.15.0", @@ -2505,15 +2504,6 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "dev": true, - "bin": { - "color-support": "bin.js" - } - }, "node_modules/colorette": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", @@ -2858,15 +2848,6 @@ "node": ">=8" } }, - "node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -4035,12 +4016,6 @@ "node": ">=0.8.x" } }, - "node_modules/events-to-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/events-to-array/-/events-to-array-1.1.2.tgz", - "integrity": "sha512-inRWzRY7nG+aXZxBzEqYKB3HPgwflZRopAjDCHv0whhRx+MTUr1ei0ICZUypdyE0HRm4L2d5VEcIqLD6yl+BFA==", - "dev": true - }, "node_modules/execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", @@ -8405,84 +8380,6 @@ "url": "https://opencollective.com/unts" } }, - "node_modules/tap-mocha-reporter": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/tap-mocha-reporter/-/tap-mocha-reporter-5.0.4.tgz", - "integrity": "sha512-J+YMO8B7lq1O6Zxd/jeuG27vJ+Y4tLiRMKPSb7KR6FVh86k3Rq1TwYc2GKPyIjCbzzdMdReh3Vfz9L5cg1Z2Bw==", - "dev": true, - "dependencies": { - "color-support": "^1.1.0", - "debug": "^4.1.1", - "diff": "^4.0.1", - "escape-string-regexp": "^2.0.0", - "glob": "^7.0.5", - "tap-parser": "^11.0.0", - "tap-yaml": "^1.0.0", - "unicode-length": "^2.0.2" - }, - "bin": { - "tap-mocha-reporter": "index.js" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/tap-mocha-reporter/node_modules/escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/tap-parser": { - "version": "11.0.2", - "resolved": "https://registry.npmjs.org/tap-parser/-/tap-parser-11.0.2.tgz", - "integrity": "sha512-6qGlC956rcORw+fg7Fv1iCRAY8/bU9UabUAhs3mXRH6eRmVZcNPLheSXCYaVaYeSwx5xa/1HXZb1537YSvwDZg==", - "dev": true, - "dependencies": { - "events-to-array": "^1.0.1", - "minipass": "^3.1.6", - "tap-yaml": "^1.0.0" - }, - "bin": { - "tap-parser": "bin/cmd.js" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/tap-parser/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/tap-yaml": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/tap-yaml/-/tap-yaml-1.0.2.tgz", - "integrity": "sha512-GegASpuqBnRNdT1U+yuUPZ8rEU64pL35WPBpCISWwff4dErS2/438barz7WFJl4Nzh3Y05tfPidZnH+GaV1wMg==", - "dev": true, - "dependencies": { - "yaml": "^1.10.2" - } - }, - "node_modules/tap-yaml/node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, "node_modules/tapable": { "version": "0.1.10", "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.1.10.tgz", @@ -8979,15 +8876,6 @@ "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", "dev": true }, - "node_modules/unicode-length": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-length/-/unicode-length-2.1.0.tgz", - "integrity": "sha512-4bV582zTV9Q02RXBxSUMiuN/KHo5w4aTojuKTNT96DIKps/SIawFp7cS5Mu25VuY1AioGXrmYyzKZUzh8OqoUw==", - "dev": true, - "dependencies": { - "punycode": "^2.0.0" - } - }, "node_modules/unicorn-magic": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", @@ -11792,12 +11680,6 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "dev": true - }, "colorette": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", @@ -12042,12 +11924,6 @@ "integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==", "dev": true }, - "diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true - }, "dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -12900,12 +12776,6 @@ "dev": true, "peer": true }, - "events-to-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/events-to-array/-/events-to-array-1.1.2.tgz", - "integrity": "sha512-inRWzRY7nG+aXZxBzEqYKB3HPgwflZRopAjDCHv0whhRx+MTUr1ei0ICZUypdyE0HRm4L2d5VEcIqLD6yl+BFA==", - "dev": true - }, "execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", @@ -16018,69 +15888,6 @@ "tslib": "^2.6.2" } }, - "tap-mocha-reporter": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/tap-mocha-reporter/-/tap-mocha-reporter-5.0.4.tgz", - "integrity": "sha512-J+YMO8B7lq1O6Zxd/jeuG27vJ+Y4tLiRMKPSb7KR6FVh86k3Rq1TwYc2GKPyIjCbzzdMdReh3Vfz9L5cg1Z2Bw==", - "dev": true, - "requires": { - "color-support": "^1.1.0", - "debug": "^4.1.1", - "diff": "^4.0.1", - "escape-string-regexp": "^2.0.0", - "glob": "^7.0.5", - "tap-parser": "^11.0.0", - "tap-yaml": "^1.0.0", - "unicode-length": "^2.0.2" - }, - "dependencies": { - "escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true - } - } - }, - "tap-parser": { - "version": "11.0.2", - "resolved": "https://registry.npmjs.org/tap-parser/-/tap-parser-11.0.2.tgz", - "integrity": "sha512-6qGlC956rcORw+fg7Fv1iCRAY8/bU9UabUAhs3mXRH6eRmVZcNPLheSXCYaVaYeSwx5xa/1HXZb1537YSvwDZg==", - "dev": true, - "requires": { - "events-to-array": "^1.0.1", - "minipass": "^3.1.6", - "tap-yaml": "^1.0.0" - }, - "dependencies": { - "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - } - } - }, - "tap-yaml": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/tap-yaml/-/tap-yaml-1.0.2.tgz", - "integrity": "sha512-GegASpuqBnRNdT1U+yuUPZ8rEU64pL35WPBpCISWwff4dErS2/438barz7WFJl4Nzh3Y05tfPidZnH+GaV1wMg==", - "dev": true, - "requires": { - "yaml": "^1.10.2" - }, - "dependencies": { - "yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "dev": true - } - } - }, "tapable": { "version": "0.1.10", "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.1.10.tgz", @@ -16458,15 +16265,6 @@ "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", "dev": true }, - "unicode-length": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-length/-/unicode-length-2.1.0.tgz", - "integrity": "sha512-4bV582zTV9Q02RXBxSUMiuN/KHo5w4aTojuKTNT96DIKps/SIawFp7cS5Mu25VuY1AioGXrmYyzKZUzh8OqoUw==", - "dev": true, - "requires": { - "punycode": "^2.0.0" - } - }, "unicorn-magic": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", diff --git a/package.json b/package.json index 7edeebe..da33bdc 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ "lint": "xo && npm run lint:md", "lint:md": "prettier --parser markdown '**/*.md' --check", "prepare": "husky install", - "test": "NODE_NO_WARNINGS=1 node --require tsx/cjs --test test/index.ts | tap-mocha-reporter spec", + "test": "NODE_NO_WARNINGS=1 node --require tsx/cjs --test test/index.ts", "test:coverage": "NODE_NO_WARNINGS=1 c8 node --require tsx/cjs --test test/index.ts", "test:watch": "NODE_NO_WARNINGS=1 node --require tsx/cjs --watch --test test/index.ts", "vscode:prepublish": "npm run check && npm run build" @@ -213,7 +213,6 @@ "prettier": "^3.2.4", "prettier-plugin-packagejson": "^2.4.9", "rimraf": "^5.0.5", - "tap-mocha-reporter": "^5.0.4", "tsx": "^4.7.0", "typescript": "^5.3.3", "vsce": "^2.15.0", diff --git a/test/code-actions-builder.test.ts b/test/code-actions-builder.test.ts index e69de29..cbe4758 100644 --- a/test/code-actions-builder.test.ts +++ b/test/code-actions-builder.test.ts @@ -0,0 +1,91 @@ +import {test, describe} from 'node:test'; +import assert from 'node:assert'; +import {TextDocument} from 'vscode-languageserver-textdocument'; +import { + CodeAction, + Diagnostic, + Range, + Position, + DiagnosticSeverity, + CodeActionKind, + uinteger, + type CodeActionParams +} from 'vscode-languageserver'; +import {QuickFixCodeActionsBuilder} from '../server/code-actions-builder'; + +const testTextDocument: TextDocument = TextDocument.create( + 'file:///test.js', + 'javascript', + 1, + 'const foo = 1;\nconst bar = 2;\n' +); + +describe('QuickFixCodeActionsBuilder:', () => { + test('Server is a function', (t) => { + assert.strictEqual(typeof QuickFixCodeActionsBuilder, 'function'); + }); + + test('ignores non xo code actions', (t) => { + const diagnostic = Diagnostic.create( + Range.create(Position.create(0, 0), Position.create(0, 0)), + 'test message', + DiagnosticSeverity.Error, + 'test', + 'non-xo' + ); + + const builder = new QuickFixCodeActionsBuilder(testTextDocument, [diagnostic], undefined); + + const codeAction = builder.build(); + + assert.deepStrictEqual(codeAction, []); + }); + + describe('Disable rule actions:', () => { + const diagnostic = Diagnostic.create( + Range.create(Position.create(0, 0), Position.create(0, 0)), + 'test message', + DiagnosticSeverity.Error, + 'test-rule', + 'XO' + ); + + const builder = new QuickFixCodeActionsBuilder(testTextDocument, [diagnostic], undefined); + test('Creates ignore same line code action', (t) => { + const codeActions = builder.build(); + assert.equal(Array.isArray(codeActions) && codeActions.length === 3, true); + const codeAction = codeActions.find( + (action) => action.title === `Ignore Rule ${diagnostic.code}: Same Line` + ); + assert.strictEqual(codeAction?.kind, CodeActionKind.QuickFix); + assert.strictEqual( + codeAction?.edit?.changes?.[testTextDocument.uri]?.[0].newText, + ` // eslint-disable-line ${diagnostic.code}` + ); + }); + + test('Creates ignore line above code action', (t) => { + const codeActions = builder.build(); + const codeAction = codeActions.find( + (action) => action.title === `Ignore Rule ${diagnostic.code}: Line Above` + ); + assert.strictEqual(codeAction?.kind, CodeActionKind.QuickFix); + assert.strictEqual( + codeAction?.edit?.changes?.[testTextDocument.uri]?.[0].newText, + `// eslint-disable-next-line ${diagnostic.code}\n` + ); + }); + + test('Creates ignore entire file code action', (t) => { + const codeActions = builder.build(); + const codeAction = codeActions.find( + (action) => action.title === `Ignore Rule ${diagnostic.code}: Entire File` + ); + assert.strictEqual(codeAction?.kind, CodeActionKind.QuickFix); + assert.strictEqual( + codeAction?.edit?.changes?.[testTextDocument.uri]?.[0].newText, + `/* eslint-disable ${diagnostic.code} */\n` + ); + }); + }); +}); diff --git a/test/index.ts b/test/index.ts index 3cc5e57..0c9c7d2 100644 --- a/test/index.ts +++ b/test/index.ts @@ -6,3 +6,4 @@ import './server.test.js'; import './lsp/document-sync.test.js'; import './lsp/initialization.test.js'; import './lsp/code-actions.test.js'; +import './code-actions-builder.test.js'; diff --git a/test/stubs.ts b/test/stubs.ts index 243d8f1..65cb5e9 100644 --- a/test/stubs.ts +++ b/test/stubs.ts @@ -31,7 +31,7 @@ export const getIgnoreSameLineCodeAction = () => ({ Position.create(0, uinteger.MAX_VALUE), Position.create(0, uinteger.MAX_VALUE) ), - newText: ' // eslint-disable-line test' + newText: ' // eslint-disable-line test' } ] }