From 152e242d85de12457a4a52751d98e7af42a5975c Mon Sep 17 00:00:00 2001 From: Gareth Jones Date: Thu, 15 Aug 2024 07:26:11 +1200 Subject: [PATCH 1/8] test: introduce flat compat rule tester --- package-lock.json | 331 ++++++++++++++---------------- package.json | 1 + tests/lib/FlatCompatRuleTester.ts | 191 +++++++++++++++++ tests/lib/test-utils.ts | 4 +- 4 files changed, 348 insertions(+), 179 deletions(-) create mode 100644 tests/lib/FlatCompatRuleTester.ts diff --git a/package-lock.json b/package-lock.json index a01dd55f..d6176697 100644 --- a/package-lock.json +++ b/package-lock.json @@ -42,6 +42,7 @@ "npm-run-all2": "^5.0.2", "prettier": "^3.3.3", "semantic-release": "^19.0.5", + "semver": "^7.6.3", "ts-node": "^10.9.2", "typescript": "5.0.4" }, @@ -118,6 +119,16 @@ "url": "https://opencollective.com/babel" } }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/@babel/eslint-parser": { "version": "7.25.8", "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.25.8.tgz", @@ -136,6 +147,16 @@ "eslint": "^7.5.0 || ^8.0.0 || ^9.0.0" } }, + "node_modules/@babel/eslint-parser/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/@babel/eslint-plugin": { "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/eslint-plugin/-/eslint-plugin-7.25.7.tgz", @@ -183,6 +204,16 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/@babel/helper-module-imports": { "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.7.tgz", @@ -3109,18 +3140,6 @@ "node": ">=6" } }, - "node_modules/@semantic-release/npm/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@semantic-release/release-notes-generator": { "version": "10.0.3", "resolved": "https://registry.npmjs.org/@semantic-release/release-notes-generator/-/release-notes-generator-10.0.3.tgz", @@ -3650,18 +3669,6 @@ } } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@typescript-eslint/parser": { "version": "5.62.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz", @@ -3770,17 +3777,6 @@ } } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@typescript-eslint/utils": { "version": "5.62.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", @@ -3806,17 +3802,6 @@ "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/@typescript-eslint/utils/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@typescript-eslint/visitor-keys": { "version": "5.62.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", @@ -4861,6 +4846,16 @@ "node": ">=10" } }, + "node_modules/conventional-changelog-writer/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/conventional-commits-filter": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-2.0.7.tgz", @@ -5977,6 +5972,16 @@ "node": ">=0.10.0" } }, + "node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/eslint-plugin-jest": { "version": "27.9.0", "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.9.0.tgz", @@ -6034,6 +6039,16 @@ "eslint": ">=5.16.0" } }, + "node_modules/eslint-plugin-node/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/eslint-plugin-promise": { "version": "6.6.0", "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.6.0.tgz", @@ -7731,18 +7746,6 @@ "semver": "^7.6.3" } }, - "node_modules/is-bun-module/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/is-callable": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", @@ -8099,6 +8102,16 @@ "node": ">=8" } }, + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/istanbul-lib-report": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", @@ -10397,18 +10410,6 @@ "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", "dev": true }, - "node_modules/jest-snapshot/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/jest-snapshot/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -11874,18 +11875,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/make-dir/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", @@ -12218,18 +12207,6 @@ "node": ">=10" } }, - "node_modules/normalize-package-data/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -16131,18 +16108,6 @@ "node": ">=10" } }, - "node_modules/semantic-release/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/semantic-release/node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", @@ -16188,12 +16153,15 @@ } }, "node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", "bin": { "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, "node_modules/semver-diff": { @@ -16208,6 +16176,16 @@ "node": ">=8" } }, + "node_modules/semver-diff/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/semver-regex": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-3.1.4.tgz", @@ -17699,6 +17677,14 @@ "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } } }, "@babel/eslint-parser": { @@ -17710,6 +17696,14 @@ "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", "eslint-visitor-keys": "^2.1.0", "semver": "^6.3.1" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } } }, "@babel/eslint-plugin": { @@ -17744,6 +17738,14 @@ "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } } }, "@babel/helper-module-imports": { @@ -19962,12 +19964,6 @@ "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", "dev": true - }, - "semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true } } }, @@ -20355,14 +20351,6 @@ "natural-compare-lite": "^1.4.0", "semver": "^7.3.7", "tsutils": "^3.21.0" - }, - "dependencies": { - "semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true - } } }, "@typescript-eslint/parser": { @@ -20415,13 +20403,6 @@ "is-glob": "^4.0.3", "semver": "^7.3.7", "tsutils": "^3.21.0" - }, - "dependencies": { - "semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==" - } } }, "@typescript-eslint/utils": { @@ -20437,13 +20418,6 @@ "@typescript-eslint/typescript-estree": "5.62.0", "eslint-scope": "^5.1.1", "semver": "^7.3.7" - }, - "dependencies": { - "semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==" - } } }, "@typescript-eslint/visitor-keys": { @@ -21189,6 +21163,14 @@ "semver": "^6.0.0", "split": "^1.0.0", "through2": "^4.0.0" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } } }, "conventional-commits-filter": { @@ -22086,6 +22068,12 @@ "requires": { "esutils": "^2.0.2" } + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true } } }, @@ -22117,6 +22105,14 @@ "minimatch": "^3.0.4", "resolve": "^1.10.1", "semver": "^6.1.0" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } } }, "eslint-plugin-promise": { @@ -23218,14 +23214,6 @@ "dev": true, "requires": { "semver": "^7.6.3" - }, - "dependencies": { - "semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true - } } }, "is-callable": { @@ -23456,6 +23444,14 @@ "@istanbuljs/schema": "^0.1.2", "istanbul-lib-coverage": "^3.2.0", "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } } }, "istanbul-lib-report": { @@ -25283,12 +25279,6 @@ "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", "dev": true }, - "semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true - }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -26277,14 +26267,6 @@ "dev": true, "requires": { "semver": "^7.5.3" - }, - "dependencies": { - "semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true - } } }, "make-error": { @@ -26528,14 +26510,6 @@ "is-core-module": "^2.5.0", "semver": "^7.3.4", "validate-npm-package-license": "^3.0.1" - }, - "dependencies": { - "semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true - } } }, "normalize-path": { @@ -29274,12 +29248,6 @@ "yaml": "^1.10.0" } }, - "semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true - }, "wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", @@ -29315,10 +29283,9 @@ } }, "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==" }, "semver-diff": { "version": "3.1.1", @@ -29327,6 +29294,14 @@ "dev": true, "requires": { "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } } }, "semver-regex": { diff --git a/package.json b/package.json index 7f5159fc..8bfa55a2 100644 --- a/package.json +++ b/package.json @@ -84,6 +84,7 @@ "npm-run-all2": "^5.0.2", "prettier": "^3.3.3", "semantic-release": "^19.0.5", + "semver": "^7.6.3", "ts-node": "^10.9.2", "typescript": "5.0.4" }, diff --git a/tests/lib/FlatCompatRuleTester.ts b/tests/lib/FlatCompatRuleTester.ts new file mode 100644 index 00000000..b3ef5943 --- /dev/null +++ b/tests/lib/FlatCompatRuleTester.ts @@ -0,0 +1,191 @@ +import { TSESLint } from '@typescript-eslint/utils'; +import { version as eslintVersion } from 'eslint/package.json'; +import * as semver from 'semver'; + +export const usingFlatConfig = semver.major(eslintVersion) >= 9; + +declare module '@typescript-eslint/utils/dist/ts-eslint' { + // eslint-disable-next-line @typescript-eslint/no-namespace + export namespace FlatConfig { + export interface LinterOptions { + /** + * A Boolean value indicating if inline configuration is allowed. + */ + noInlineConfig?: boolean; + /** + * A severity string indicating if and how unused disable and enable + * directives should be tracked and reported. For legacy compatibility, `true` + * is equivalent to `"warn"` and `false` is equivalent to `"off"`. + * @default "off" + */ + reportUnusedDisableDirectives?: + | TSESLint.Linter.Severity + | TSESLint.Linter.SeverityString + | boolean; + } + + export interface Config { + /** + * An string to identify the configuration object. Used in error messages and inspection tools. + */ + name?: string; + /** + * An array of glob patterns indicating the files that the configuration object should apply to. + * If not specified, the configuration object applies to all files matched by any other configuration object. + */ + files?: (string | string[])[]; + /** + * An array of glob patterns indicating the files that the configuration object should not apply to. + * If not specified, the configuration object applies to all files matched by files. + */ + ignores?: string[]; + /** + * An object containing settings related to how JavaScript is configured for linting. + */ + languageOptions?: LanguageOptions; + /** + * An object containing settings related to the linting process. + */ + linterOptions?: LinterOptions; + /** + * An object containing a name-value mapping of plugin names to plugin objects. + * When `files` is specified, these plugins are only available to the matching files. + */ + plugins?: unknown; + /** + * Either an object containing `preprocess()` and `postprocess()` methods or + * a string indicating the name of a processor inside of a plugin + * (i.e., `"pluginName/processorName"`). + */ + processor?: string | TSESLint.Linter.Processor; + /** + * An object containing the configured rules. + * When `files` or `ignores` are specified, these rule configurations are only available to the matching files. + */ + rules?: TSESLint.Linter.RulesRecord; + /** + * An object containing name-value pairs of information that should be available to all rules. + */ + settings?: TSESLint.SharedConfigurationSettings; + } + + export type ParserOptions = TSESLint.Linter.ParserOptions; + + export interface LanguageOptions { + /** + * The version of ECMAScript to support. + * May be any year (i.e., `2022`) or version (i.e., `5`). + * Set to `"latest"` for the most recent supported version. + * @default "latest" + */ + ecmaVersion?: Required['ecmaVersion']; + /** + * An object specifying additional objects that should be added to the global scope during linting. + */ + globals?: + | Record + | undefined; + /** + * An object containing a `parse()` method or a `parseForESLint()` method. + * @default + * ``` + * // https://github.com/eslint/espree + * require('espree') + * ``` + */ + parser?: unknown; + /** + * An object specifying additional options that are passed directly to the parser. + * The available options are parser-dependent. + */ + parserOptions?: ParserOptions | undefined; + /** + * The type of JavaScript source code. + * Possible values are `"script"` for traditional script files, `"module"` for ECMAScript modules (ESM), and `"commonjs"` for CommonJS files. + * @default + * ``` + * // for `.js` and `.mjs` files + * "module" + * // for `.cjs` files + * "commonjs" + * ``` + */ + sourceType?: Required['sourceType']; + } + } +} + +export class FlatCompatRuleTester extends TSESLint.RuleTester { + public constructor(testerConfig?: TSESLint.RuleTesterConfig) { + super(FlatCompatRuleTester._flatCompat(testerConfig)); + } + + public override run< + TMessageIds extends string, + TOptions extends readonly unknown[], + >( + ruleName: string, + rule: TSESLint.RuleModule, + tests: TSESLint.RunTests + ) { + super.run(ruleName, rule, { + valid: tests.valid.map((t) => FlatCompatRuleTester._flatCompat(t)), + invalid: tests.invalid.map((t) => FlatCompatRuleTester._flatCompat(t)), + }); + } + + /* istanbul ignore next */ + private static _flatCompat< + T extends + | undefined + | TSESLint.RuleTesterConfig + | string + | TSESLint.ValidTestCase + | TSESLint.InvalidTestCase, + >(config: T): T { + if (!config || !usingFlatConfig || typeof config === 'string') { + return config; + } + + const obj: TSESLint.FlatConfig.Config & { + languageOptions: TSESLint.FlatConfig.LanguageOptions & { + parserOptions: TSESLint.FlatConfig.ParserOptions; + }; + } = { + languageOptions: { parserOptions: {} }, + }; + + for (const [key, value] of Object.entries(config)) { + if (key === 'parser') { + obj.languageOptions.parser = require(value as string); + + continue; + } + + if (key === 'parserOptions') { + for (const [option, val] of Object.entries( + value as { [s: string]: unknown } + )) { + if (option === 'ecmaVersion' || option === 'sourceType') { + // @ts-expect-error: TS thinks the value could the opposite type of whatever option is + obj.languageOptions[option] = + val as TSESLint.FlatConfig.LanguageOptions[ + | 'ecmaVersion' + | 'sourceType']; + + continue; + } + + obj.languageOptions.parserOptions[option] = val; + } + + continue; + } + + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + obj[key as keyof typeof obj] = value; + } + + return obj as unknown as T; + } +} diff --git a/tests/lib/test-utils.ts b/tests/lib/test-utils.ts index c9640129..aed679c7 100644 --- a/tests/lib/test-utils.ts +++ b/tests/lib/test-utils.ts @@ -2,11 +2,13 @@ import { resolve } from 'path'; import { TSESLint } from '@typescript-eslint/utils'; +import { FlatCompatRuleTester } from './FlatCompatRuleTester'; + const DEFAULT_TEST_CASE_CONFIG = { filename: 'MyComponent.test.js', }; -class TestingLibraryRuleTester extends TSESLint.RuleTester { +class TestingLibraryRuleTester extends FlatCompatRuleTester { run>( ruleName: string, rule: TSESLint.RuleModule, From 5daaa0dbd8a1749dcadb63572a7e9768e754b909 Mon Sep 17 00:00:00 2001 From: Gareth Jones Date: Thu, 15 Aug 2024 07:39:11 +1200 Subject: [PATCH 2/8] test: remove duplicate cases --- tests/lib/rules/await-async-events.test.ts | 10 +++--- tests/lib/rules/await-async-utils.test.ts | 31 +++++++++------- tests/lib/rules/no-dom-import.test.ts | 36 +++++++++++++------ tests/lib/rules/no-node-access.test.ts | 10 +++--- tests/lib/rules/prefer-find-by.test.ts | 10 +++--- tests/lib/rules/prefer-query-matchers.test.ts | 30 +++++++++++----- 6 files changed, 82 insertions(+), 45 deletions(-) diff --git a/tests/lib/rules/await-async-events.test.ts b/tests/lib/rules/await-async-events.test.ts index 82a9c347..6489dec8 100644 --- a/tests/lib/rules/await-async-events.test.ts +++ b/tests/lib/rules/await-async-events.test.ts @@ -142,7 +142,7 @@ ruleTester.run(RULE_NAME, rule, { 'testing-library/utils-module': 'test-utils', }, code: ` - import { fireEvent } from 'somewhere-else' + import { fireEvent } from 'somewhere-else' // not ${testingFramework} test('unhandled promise from event not related to TL is valid', async () => { fireEvent.${eventMethod}(getByLabelText('username')) }) @@ -154,7 +154,7 @@ ruleTester.run(RULE_NAME, rule, { 'testing-library/utils-module': 'test-utils', }, code: ` - import { fireEvent } from 'test-utils' + import { fireEvent } from 'test-utils' // implicitly ${testingFramework} test('await promise from event method imported from custom module is valid', async () => { await fireEvent.${eventMethod}(getByLabelText('username')) }) @@ -166,7 +166,7 @@ ruleTester.run(RULE_NAME, rule, { // valid use case without call expression // so there is no innermost function scope found code: ` - import { fireEvent } from 'test-utils' + import { fireEvent } from 'test-utils' // implicitly using ${testingFramework} test('edge case for innermost function without call expression', async () => { function triggerEvent() { doSomething() @@ -611,7 +611,7 @@ ruleTester.run(RULE_NAME, rule, { 'testing-library/utils-module': 'test-utils', }, code: ` - import { fireEvent } from 'test-utils' + import { fireEvent } from 'test-utils' // implicitly using ${testingFramework} test( 'unhandled promise from event method imported from custom module with aggressive reporting opted-out is invalid', () => { @@ -628,7 +628,7 @@ ruleTester.run(RULE_NAME, rule, { ], options: [{ eventModule: 'fireEvent' }], output: ` - import { fireEvent } from 'test-utils' + import { fireEvent } from 'test-utils' // implicitly using ${testingFramework} test( 'unhandled promise from event method imported from custom module with aggressive reporting opted-out is invalid', async () => { diff --git a/tests/lib/rules/await-async-utils.test.ts b/tests/lib/rules/await-async-utils.test.ts index 1a5490c9..1759ebdc 100644 --- a/tests/lib/rules/await-async-utils.test.ts +++ b/tests/lib/rules/await-async-utils.test.ts @@ -126,7 +126,7 @@ ruleTester.run(RULE_NAME, rule, { 'testing-library/utils-module': 'test-utils', }, code: ` - import { ${asyncUtil} } from 'some-other-library'; + import { ${asyncUtil} } from 'some-other-library'; // rather than ${testingFramework} test( 'aggressive reporting disabled - util "${asyncUtil}" which is not related to testing library is valid', async () => { @@ -140,7 +140,7 @@ ruleTester.run(RULE_NAME, rule, { 'testing-library/utils-module': 'test-utils', }, code: ` - import * as asyncUtils from 'some-other-library'; + import * as asyncUtils from 'some-other-library'; // rather than ${testingFramework} test( 'aggressive reporting disabled - util "asyncUtils.${asyncUtil}" which is not related to testing library is valid', async () => { @@ -242,7 +242,7 @@ ruleTester.run(RULE_NAME, rule, { code: ` test('using unrelated promises with Promise.all is valid', async () => { Promise.all([ - waitForNotRelatedToTestingLibrary(), + waitForNotRelatedToTestingLibrary(), // completely unrelated to ${testingFramework} promise1, await foo().then(() => baz()) ]) @@ -262,6 +262,7 @@ ruleTester.run(RULE_NAME, rule, { }, ...ASYNC_UTILS.map((asyncUtil) => ({ code: ` + // using ${testingFramework} implicitly function setup() { const utils = render(); @@ -297,7 +298,7 @@ ruleTester.run(RULE_NAME, rule, { ...ASYNC_UTILS.map((asyncUtil) => ({ code: ` import React from 'react'; - import { render, act } from '@testing-library/react'; + import { render, act } from '${testingFramework}'; const doWithAct = async (timeout) => { await act(async () => await ${asyncUtil}(screen.getByTestId('my-test'))); @@ -491,7 +492,7 @@ ruleTester.run(RULE_NAME, rule, { (asyncUtil) => ({ code: ` - import { ${asyncUtil} } from 'some-other-library'; + import { ${asyncUtil} } from 'some-other-library'; // rather than ${testingFramework} test( 'aggressive reporting - util "${asyncUtil}" which is not related to testing library is invalid', async () => { @@ -539,7 +540,7 @@ ruleTester.run(RULE_NAME, rule, { (asyncUtil) => ({ code: ` - import * as asyncUtils from 'some-other-library'; + import * as asyncUtils from 'some-other-library'; // rather than ${testingFramework} test( 'aggressive reporting - util "asyncUtils.${asyncUtil}" which is not related to testing library is invalid', async () => { @@ -561,6 +562,7 @@ ruleTester.run(RULE_NAME, rule, { (asyncUtil) => ({ code: ` + // using ${testingFramework} implicitly function setup() { const utils = render(); @@ -578,7 +580,7 @@ ruleTester.run(RULE_NAME, rule, { `, errors: [ { - line: 14, + line: 15, column: 11, messageId: 'asyncUtilWrapper', data: { name: 'waitForAsyncUtil' }, @@ -590,6 +592,7 @@ ruleTester.run(RULE_NAME, rule, { (asyncUtil) => ({ code: ` + // using ${testingFramework} implicitly function setup() { const utils = render(); @@ -608,7 +611,7 @@ ruleTester.run(RULE_NAME, rule, { `, errors: [ { - line: 15, + line: 16, column: 11, messageId: 'asyncUtilWrapper', data: { name: 'myAlias' }, @@ -620,6 +623,7 @@ ruleTester.run(RULE_NAME, rule, { (asyncUtil) => ({ code: ` + // using ${testingFramework} implicitly function setup() { const utils = render(); @@ -637,7 +641,7 @@ ruleTester.run(RULE_NAME, rule, { `, errors: [ { - line: 14, + line: 15, column: 17, messageId: 'asyncUtilWrapper', data: { name: 'waitForAsyncUtil' }, @@ -649,6 +653,7 @@ ruleTester.run(RULE_NAME, rule, { (asyncUtil) => ({ code: ` + // using ${testingFramework} implicitly function setup() { const utils = render(); @@ -666,7 +671,7 @@ ruleTester.run(RULE_NAME, rule, { `, errors: [ { - line: 14, + line: 15, column: 11, messageId: 'asyncUtilWrapper', data: { name: 'myAlias' }, @@ -678,6 +683,7 @@ ruleTester.run(RULE_NAME, rule, { (asyncUtil) => ({ code: ` + // using ${testingFramework} implicitly function setup() { const utils = render(); @@ -694,7 +700,7 @@ ruleTester.run(RULE_NAME, rule, { `, errors: [ { - line: 13, + line: 14, column: 19, messageId: 'asyncUtilWrapper', data: { name: 'waitForAsyncUtil' }, @@ -706,6 +712,7 @@ ruleTester.run(RULE_NAME, rule, { (asyncUtil) => ({ code: ` + // using ${testingFramework} implicitly function setup() { const utils = render(); @@ -723,7 +730,7 @@ ruleTester.run(RULE_NAME, rule, { `, errors: [ { - line: 14, + line: 15, column: 11, messageId: 'asyncUtilWrapper', data: { name: 'myAlias' }, diff --git a/tests/lib/rules/no-dom-import.test.ts b/tests/lib/rules/no-dom-import.test.ts index e515eb5c..98d240a3 100644 --- a/tests/lib/rules/no-dom-import.test.ts +++ b/tests/lib/rules/no-dom-import.test.ts @@ -31,22 +31,38 @@ ruleTester.run(RULE_NAME, rule, { 'import { foo } from "foo"', 'import "foo"', ...SUPPORTED_TESTING_FRAMEWORKS.flatMap(({ oldName, newName }) => - [oldName, newName].flatMap((testingFramework) => [ - `import { fireEvent } from "${testingFramework}"`, - `import * as testing from "${testingFramework}"`, - `import "${testingFramework}"`, - ]) + [oldName, newName !== oldName ? newName : null].flatMap( + (testingFramework) => { + if (!testingFramework) { + return []; + } + + return [ + `import { fireEvent } from "${testingFramework}"`, + `import * as testing from "${testingFramework}"`, + `import "${testingFramework}"`, + ]; + } + ) ), 'const { foo } = require("foo")', 'require("foo")', 'require("")', 'require()', ...SUPPORTED_TESTING_FRAMEWORKS.flatMap(({ oldName, newName }) => - [oldName, newName].flatMap((testingFramework) => [ - `const { fireEvent } = require("${testingFramework}")`, - `const { fireEvent: testing } = require("${testingFramework}")`, - `require("${testingFramework}")`, - ]) + [oldName, newName !== oldName ? newName : null].flatMap( + (testingFramework) => { + if (!testingFramework) { + return []; + } + + return [ + `const { fireEvent } = require("${testingFramework}")`, + `const { fireEvent: testing } = require("${testingFramework}")`, + `require("${testingFramework}")`, + ]; + } + ) ), { code: 'import { fireEvent } from "test-utils"', diff --git a/tests/lib/rules/no-node-access.test.ts b/tests/lib/rules/no-node-access.test.ts index f3216e7e..cdecd5a9 100644 --- a/tests/lib/rules/no-node-access.test.ts +++ b/tests/lib/rules/no-node-access.test.ts @@ -61,7 +61,7 @@ ruleTester.run(RULE_NAME, rule, { }, { code: ` - // case: code not related to testing library at all + // case: code not related to ${testingFramework} at all ReactDOM.render( @@ -116,14 +116,14 @@ ruleTester.run(RULE_NAME, rule, { 'testing-library/utils-module': 'test-utils', }, code: ` - // case: custom module set but not imported (aggressive reporting limited) + // case: custom module set but not imported using ${testingFramework} (aggressive reporting limited) const closestButton = document.getElementById('submit-btn').closest('button'); expect(closestButton).toBeInTheDocument(); `, }, { code: ` - // case: without importing TL (aggressive reporting skipped) + // case: without importing ${testingFramework} (aggressive reporting skipped) const closestButton = document.getElementById('submit-btn') expect(closestButton).toBeInTheDocument(); `, @@ -141,7 +141,7 @@ ruleTester.run(RULE_NAME, rule, { { // Example from discussions in issue #386 code: ` - import { render } from '@testing-library/react'; + import { render } from '${testingFramework}'; function Wrapper({ children }) { // this should NOT be reported @@ -165,7 +165,7 @@ ruleTester.run(RULE_NAME, rule, { 'testing-library/utils-module': 'test-utils', }, code: ` - // case: importing from custom module (aggressive reporting limited) + // case: importing from custom module for ${testingFramework} (aggressive reporting limited) import 'test-utils'; const closestButton = document.getElementById('submit-btn') expect(closestButton).toBeInTheDocument(); diff --git a/tests/lib/rules/prefer-find-by.test.ts b/tests/lib/rules/prefer-find-by.test.ts index 3bf6bed7..7c90651f 100644 --- a/tests/lib/rules/prefer-find-by.test.ts +++ b/tests/lib/rules/prefer-find-by.test.ts @@ -40,7 +40,7 @@ ruleTester.run(RULE_NAME, rule, { ...ASYNC_QUERIES_COMBINATIONS.map((queryMethod) => ({ code: ` it('tests', async () => { - const { ${queryMethod} } = setup() + const { ${queryMethod} } = setup() // implicitly using ${testingFramework} const submitButton = await ${queryMethod}('foo') }) `, @@ -251,7 +251,7 @@ ruleTester.run(RULE_NAME, rule, { }, // invalid code, as we need findBy* to be defined somewhere, but required for getting 100% coverage { - code: `const submitButton = await waitFor(() => getByText('baz', { name: 'button' }))`, + code: `const submitButton = await waitFor(() => getByText('baz', { name: 'button' })) // implicitly using ${testingFramework}`, errors: [ { messageId: 'preferFindBy', @@ -263,12 +263,12 @@ ruleTester.run(RULE_NAME, rule, { }, }, ], - output: `const submitButton = await findByText('baz', { name: 'button' })`, + output: `const submitButton = await findByText('baz', { name: 'button' }) // implicitly using ${testingFramework}`, }, // this code would be invalid too, as findByRole is not defined anywhere. { code: ` - const getByRole = render().getByRole + const getByRole = render().getByRole // implicitly using ${testingFramework} const submitButton = await waitFor(() => getByRole('baz', { name: 'button' })) `, errors: [ @@ -283,7 +283,7 @@ ruleTester.run(RULE_NAME, rule, { }, ], output: ` - const getByRole = render().getByRole + const getByRole = render().getByRole // implicitly using ${testingFramework} const submitButton = await findByRole('baz', { name: 'button' }) `, }, diff --git a/tests/lib/rules/prefer-query-matchers.test.ts b/tests/lib/rules/prefer-query-matchers.test.ts index e16cf983..908f1b27 100644 --- a/tests/lib/rules/prefer-query-matchers.test.ts +++ b/tests/lib/rules/prefer-query-matchers.test.ts @@ -24,6 +24,7 @@ type AssertionFnParams = { query: string; matcher: string; options: Options; + onlyOptions?: boolean; }; const wrapExpectInTest = (expectStatement: string) => ` @@ -39,28 +40,37 @@ const getValidAssertions = ({ query, matcher, options, + onlyOptions = false, }: AssertionFnParams): RuleValidTestCase[] => { const expectStatement = `expect(${query}('Hello'))${matcher}`; const expectScreenStatement = `expect(screen.${query}('Hello'))${matcher}`; - return [ - { - // name: `${expectStatement} with default options of empty validEntries`, - code: wrapExpectInTest(expectStatement), - }, + const casesWithOptions = [ { // name: `${expectStatement} with provided options`, code: wrapExpectInTest(expectStatement), options, }, { - // name: `${expectScreenStatement} with default options of empty validEntries`, + // name: `${expectScreenStatement} with provided options`, code: wrapExpectInTest(expectScreenStatement), + options, }, + ]; + + if (onlyOptions) { + return casesWithOptions; + } + + return [ { - // name: `${expectScreenStatement} with provided options`, + // name: `${expectStatement} with default options of empty validEntries`, + code: wrapExpectInTest(expectStatement), + }, + { + // name: `${expectScreenStatement} with default options of empty validEntries`, code: wrapExpectInTest(expectScreenStatement), - options, }, + ...casesWithOptions, ]; }; @@ -150,6 +160,7 @@ ruleTester.run(RULE_NAME, rule, { options: [ { validEntries: [{ query: 'query', matcher: 'toBeVisible' }] }, ], + onlyOptions: true, }), ], [] @@ -192,6 +203,7 @@ ruleTester.run(RULE_NAME, rule, { options: [ { validEntries: [{ query: 'query', matcher: 'toBeVisible' }] }, ], + onlyOptions: true, }), ], [] @@ -234,6 +246,7 @@ ruleTester.run(RULE_NAME, rule, { options: [ { validEntries: [{ query: 'get', matcher: 'toBeVisible' }] }, ], + onlyOptions: true, }), ], [] @@ -276,6 +289,7 @@ ruleTester.run(RULE_NAME, rule, { options: [ { validEntries: [{ query: 'get', matcher: 'toBeVisible' }] }, ], + onlyOptions: true, }), ], [] From 2776757305fe8aff209cf44c3d68ee272ea5a699 Mon Sep 17 00:00:00 2001 From: Gareth Jones Date: Thu, 15 Aug 2024 08:43:50 +1200 Subject: [PATCH 3/8] test: expect no output change with `null` --- tests/lib/rules/await-async-events.test.ts | 44 +++++----------------- tests/lib/rules/no-dom-import.test.ts | 6 +-- tests/lib/rules/prefer-find-by.test.ts | 16 +------- 3 files changed, 13 insertions(+), 53 deletions(-) diff --git a/tests/lib/rules/await-async-events.test.ts b/tests/lib/rules/await-async-events.test.ts index 6489dec8..6e16abe9 100644 --- a/tests/lib/rules/await-async-events.test.ts +++ b/tests/lib/rules/await-async-events.test.ts @@ -131,7 +131,7 @@ ruleTester.run(RULE_NAME, rule, { doSomething() return fireEvent.${eventMethod}(getByLabelText('username')) } - + await triggerEvent() }) `, @@ -172,7 +172,7 @@ ruleTester.run(RULE_NAME, rule, { doSomething() return fireEvent.focus(getByLabelText('username')) } - + const reassignedFunction = triggerEvent }) `, @@ -318,7 +318,7 @@ ruleTester.run(RULE_NAME, rule, { doSomething() return userEvent.${eventMethod}(getByLabelText('username')) } - + await triggerEvent() }) `, @@ -380,7 +380,7 @@ ruleTester.run(RULE_NAME, rule, { doSomething() return userEvent.focus(getByLabelText('username')) } - + const reassignedFunction = triggerEvent }) `, @@ -447,11 +447,7 @@ ruleTester.run(RULE_NAME, rule, { }, ], options: [{ eventModule: 'fireEvent' }], - output: ` - import { fireEvent } from '${testingFramework}' - - fireEvent.${eventMethod}(getByLabelText('username')) - `, + output: null, }) as const ), ...FIRE_EVENT_ASYNC_FUNCTIONS.map( @@ -759,16 +755,7 @@ ruleTester.run(RULE_NAME, rule, { }, ], options: [{ eventModule: 'fireEvent' }], - output: ` - import { fireEvent } from '${testingFramework}' - - function triggerEvent() { - doSomething() - return fireEvent.${eventMethod}(getByLabelText('username')) - } - - triggerEvent() - `, + output: null, }) as const ), ]), @@ -805,7 +792,7 @@ ruleTester.run(RULE_NAME, rule, { ({ code: ` import userEvent from '${testingFramework}' - + userEvent.${eventMethod}(getByLabelText('username')) `, errors: [ @@ -818,11 +805,7 @@ ruleTester.run(RULE_NAME, rule, { }, ], options: [{ eventModule: 'userEvent' }], - output: ` - import userEvent from '${testingFramework}' - - userEvent.${eventMethod}(getByLabelText('username')) - `, + output: null, }) as const ), ...USER_EVENT_ASYNC_FUNCTIONS.map( @@ -974,16 +957,7 @@ ruleTester.run(RULE_NAME, rule, { }, ], options: [{ eventModule: 'userEvent' }], - output: ` - import userEvent from '${testingFramework}' - - function triggerEvent() { - doSomething() - return userEvent.${eventMethod}(getByLabelText('username')) - } - - triggerEvent() - `, + output: null, }) as const ), ...USER_EVENT_ASYNC_FUNCTIONS.map( diff --git a/tests/lib/rules/no-dom-import.test.ts b/tests/lib/rules/no-dom-import.test.ts index 98d240a3..e5fbce0c 100644 --- a/tests/lib/rules/no-dom-import.test.ts +++ b/tests/lib/rules/no-dom-import.test.ts @@ -77,7 +77,7 @@ ruleTester.run(RULE_NAME, rule, { messageId: 'noDomImport', }, ], - output: 'import { fireEvent } from "dom-testing-library"', + output: null, }, { settings: { @@ -92,9 +92,7 @@ ruleTester.run(RULE_NAME, rule, { messageId: 'noDomImport', }, ], - output: ` - // case: dom-testing-library imported with custom module setting - import { fireEvent } from "dom-testing-library"`, + output: null, }, ...SUPPORTED_TESTING_FRAMEWORKS.flatMap( ({ configOption, oldName, newName }) => diff --git a/tests/lib/rules/prefer-find-by.test.ts b/tests/lib/rules/prefer-find-by.test.ts index 7c90651f..2f27043e 100644 --- a/tests/lib/rules/prefer-find-by.test.ts +++ b/tests/lib/rules/prefer-find-by.test.ts @@ -306,13 +306,7 @@ ruleTester.run(RULE_NAME, rule, { }, }, ], - output: ` - import { waitFor, render} from '${testingFramework}'; - it('tests', async () => { - const { getByCustomQuery } = render() - const submitButton = await waitFor(() => getByCustomQuery('baz')) - }) - `, + output: null, }, // custom query triggers the error but there is no fix - so output is the same { @@ -333,13 +327,7 @@ ruleTester.run(RULE_NAME, rule, { }, }, ], - output: ` - import {waitFor,render,screen} from '${testingFramework}'; - it('tests', async () => { - const { getByCustomQuery } = render() - const submitButton = await waitFor(() => screen.getByCustomQuery('baz')) - }) - `, + output: null, }, // presence matchers ...createScenario((waitMethod: string, queryMethod: string) => ({ From 0d6bb401d2c8a3332c6d81023e6ca95a96ef252a Mon Sep 17 00:00:00 2001 From: Gareth Jones Date: Thu, 15 Aug 2024 08:44:57 +1200 Subject: [PATCH 4/8] ci: test against ESLint v9 --- .github/workflows/verifications.yml | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/.github/workflows/verifications.yml b/.github/workflows/verifications.yml index 92d1b2a4..33f0d74b 100644 --- a/.github/workflows/verifications.yml +++ b/.github/workflows/verifications.yml @@ -35,7 +35,21 @@ jobs: fail-fast: false matrix: node: [12.22.0, 12, 14.17.0, 14, 16, 17, 18, 19, 20, 22] - eslint: [7.5, 7, 8] + eslint: [7.5, 7, 8, 9] + exclude: + # eslint@9 doesn't support < Node v18 + - node: 17 + eslint: 9 + - node: 16 + eslint: 9 + - node: 14 + eslint: 9 + - node: 14.17.0 + eslint: 9 + - node: 12 + eslint: 9 + - node: 12.22.0 + eslint: 9 steps: - name: Checkout uses: actions/checkout@v4 From fe6f5348ec7b6e81a0e01bbbd143e529388e2b55 Mon Sep 17 00:00:00 2001 From: Gareth Jones Date: Fri, 16 Aug 2024 06:59:01 +1200 Subject: [PATCH 5/8] ci: uninstall some packages for v9 to avoid an npm inf. loop bug --- .github/workflows/verifications.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/verifications.yml b/.github/workflows/verifications.yml index 33f0d74b..31948551 100644 --- a/.github/workflows/verifications.yml +++ b/.github/workflows/verifications.yml @@ -63,6 +63,10 @@ jobs: - name: Install dependencies run: npm install + # see https://github.com/npm/cli/issues/7349 + - if: ${{ matrix.eslint == 9 }} + run: npm un eslint-plugin-jest eslint-doc-generator + - name: Install ESLint v${{ matrix.eslint }} run: npm install --no-save --force eslint@${{ matrix.eslint }} From 4cfd5e201628a9432aa4599c12d88227ae123abf Mon Sep 17 00:00:00 2001 From: Gareth Jones Date: Fri, 16 Aug 2024 08:00:18 +1200 Subject: [PATCH 6/8] ci: timeout after 3 minutes --- .github/workflows/verifications.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/verifications.yml b/.github/workflows/verifications.yml index 31948551..091909f1 100644 --- a/.github/workflows/verifications.yml +++ b/.github/workflows/verifications.yml @@ -31,6 +31,7 @@ jobs: tests: name: Tests (Node v${{ matrix.node }} - ESLint v${{ matrix.eslint }}) runs-on: ubuntu-latest + timeout-minutes: 3 strategy: fail-fast: false matrix: From db558602c359f3b2ec33fcf82a3cea67c5b5c8f3 Mon Sep 17 00:00:00 2001 From: Gareth Jones Date: Fri, 18 Oct 2024 11:54:58 +1300 Subject: [PATCH 7/8] ci: uninstall more packages for inf. loop --- .github/workflows/verifications.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/verifications.yml b/.github/workflows/verifications.yml index 091909f1..ccb2b425 100644 --- a/.github/workflows/verifications.yml +++ b/.github/workflows/verifications.yml @@ -66,7 +66,7 @@ jobs: # see https://github.com/npm/cli/issues/7349 - if: ${{ matrix.eslint == 9 }} - run: npm un eslint-plugin-jest eslint-doc-generator + run: npm un @typescript-eslint/eslint-plugin eslint-plugin-jest eslint-doc-generator - name: Install ESLint v${{ matrix.eslint }} run: npm install --no-save --force eslint@${{ matrix.eslint }} From 8d487d5dad3cd64afe4e2cfb16857b19b3cd8c17 Mon Sep 17 00:00:00 2001 From: Gareth Jones Date: Fri, 18 Oct 2024 12:20:11 +1300 Subject: [PATCH 8/8] test: be consistent with comments --- tests/lib/rules/await-async-events.test.ts | 4 +- tests/lib/rules/await-async-utils.test.ts | 64 +++++++++++----------- 2 files changed, 34 insertions(+), 34 deletions(-) diff --git a/tests/lib/rules/await-async-events.test.ts b/tests/lib/rules/await-async-events.test.ts index 6e16abe9..80ffb15d 100644 --- a/tests/lib/rules/await-async-events.test.ts +++ b/tests/lib/rules/await-async-events.test.ts @@ -142,7 +142,7 @@ ruleTester.run(RULE_NAME, rule, { 'testing-library/utils-module': 'test-utils', }, code: ` - import { fireEvent } from 'somewhere-else' // not ${testingFramework} + import { fireEvent } from 'somewhere-else' // not using ${testingFramework} test('unhandled promise from event not related to TL is valid', async () => { fireEvent.${eventMethod}(getByLabelText('username')) }) @@ -154,7 +154,7 @@ ruleTester.run(RULE_NAME, rule, { 'testing-library/utils-module': 'test-utils', }, code: ` - import { fireEvent } from 'test-utils' // implicitly ${testingFramework} + import { fireEvent } from 'test-utils' // implicitly using ${testingFramework} test('await promise from event method imported from custom module is valid', async () => { await fireEvent.${eventMethod}(getByLabelText('username')) }) diff --git a/tests/lib/rules/await-async-utils.test.ts b/tests/lib/rules/await-async-utils.test.ts index 1759ebdc..fc538079 100644 --- a/tests/lib/rules/await-async-utils.test.ts +++ b/tests/lib/rules/await-async-utils.test.ts @@ -113,9 +113,9 @@ ruleTester.run(RULE_NAME, rule, { const aPromise = ${asyncUtil}(() => document.querySelector('div.getOuttaHere') ); - + doSomethingElse(); - + return aPromise; }; }); @@ -228,7 +228,7 @@ ruleTester.run(RULE_NAME, rule, { ...ASYNC_UTILS.map((asyncUtil) => ({ code: ` import { ${asyncUtil} } from '${testingFramework}'; - + function waitForSomethingAsync() { return ${asyncUtil}(() => somethingAsync()) } @@ -262,14 +262,14 @@ ruleTester.run(RULE_NAME, rule, { }, ...ASYNC_UTILS.map((asyncUtil) => ({ code: ` - // using ${testingFramework} implicitly + // implicitly using ${testingFramework} function setup() { const utils = render(); - + const waitForAsyncUtil = () => { return ${asyncUtil}(screen.queryByTestId('my-test-id')); }; - + return { waitForAsyncUtil, ...utils }; } @@ -287,7 +287,7 @@ ruleTester.run(RULE_NAME, rule, { const { waitForAsyncUtil: myDestructuredAlias } = setup(); await myDestructuredAlias(); - + const { user, ...rest } = setup(); await rest.waitForAsyncUtil(); @@ -299,23 +299,23 @@ ruleTester.run(RULE_NAME, rule, { code: ` import React from 'react'; import { render, act } from '${testingFramework}'; - + const doWithAct = async (timeout) => { await act(async () => await ${asyncUtil}(screen.getByTestId('my-test'))); }; - + describe('Component', () => { const mock = jest.fn(); - + it('test', async () => { let Component = () => { mock(1); return
; }; render(); - + await doWithAct(500); - + const myNumberTestVar = 1; const myBooleanTestVar = false; const myArrayTestVar = [1, 2]; @@ -468,7 +468,7 @@ ruleTester.run(RULE_NAME, rule, { ({ code: ` import { ${asyncUtil}, render } from '${testingFramework}'; - + function waitForSomethingAsync() { return ${asyncUtil}(() => somethingAsync()) } @@ -515,7 +515,7 @@ ruleTester.run(RULE_NAME, rule, { ({ code: ` import { ${asyncUtil}, render } from '${testingFramework}'; - + function waitForSomethingAsync() { return ${asyncUtil}(() => somethingAsync()) } @@ -562,14 +562,14 @@ ruleTester.run(RULE_NAME, rule, { (asyncUtil) => ({ code: ` - // using ${testingFramework} implicitly + // implicitly using ${testingFramework} function setup() { const utils = render(); - + const waitForAsyncUtil = () => { return ${asyncUtil}(screen.queryByTestId('my-test-id')); }; - + return { waitForAsyncUtil, ...utils }; } @@ -592,14 +592,14 @@ ruleTester.run(RULE_NAME, rule, { (asyncUtil) => ({ code: ` - // using ${testingFramework} implicitly + // implicitly using ${testingFramework} function setup() { const utils = render(); - + const waitForAsyncUtil = () => { return ${asyncUtil}(screen.queryByTestId('my-test-id')); }; - + return { waitForAsyncUtil, ...utils }; } @@ -623,14 +623,14 @@ ruleTester.run(RULE_NAME, rule, { (asyncUtil) => ({ code: ` - // using ${testingFramework} implicitly + // implicitly using ${testingFramework} function setup() { const utils = render(); - + const waitForAsyncUtil = () => { return ${asyncUtil}(screen.queryByTestId('my-test-id')); }; - + return { waitForAsyncUtil, ...utils }; } @@ -653,14 +653,14 @@ ruleTester.run(RULE_NAME, rule, { (asyncUtil) => ({ code: ` - // using ${testingFramework} implicitly + // implicitly using ${testingFramework} function setup() { const utils = render(); - + const waitForAsyncUtil = () => { return ${asyncUtil}(screen.queryByTestId('my-test-id')); }; - + return { waitForAsyncUtil, ...utils }; } @@ -683,14 +683,14 @@ ruleTester.run(RULE_NAME, rule, { (asyncUtil) => ({ code: ` - // using ${testingFramework} implicitly + // implicitly using ${testingFramework} function setup() { const utils = render(); - + const waitForAsyncUtil = () => { return ${asyncUtil}(screen.queryByTestId('my-test-id')); }; - + return { waitForAsyncUtil, ...utils }; } @@ -712,14 +712,14 @@ ruleTester.run(RULE_NAME, rule, { (asyncUtil) => ({ code: ` - // using ${testingFramework} implicitly + // implicitly using ${testingFramework} function setup() { const utils = render(); - + const waitForAsyncUtil = () => { return ${asyncUtil}(screen.queryByTestId('my-test-id')); }; - + return { waitForAsyncUtil, ...utils }; }