From edd395a7d39cb081f04c9b481a6ac67cce492ef4 Mon Sep 17 00:00:00 2001 From: Michael Novotny Date: Thu, 30 Jun 2022 11:31:33 -0500 Subject: [PATCH] Adds tests to ensure `eslint-plugin-next`'s available rules are properly exported and recommended rules are correctly defined. (#38183) * Adds tests to ensure `eslint-plugin-next`'s available rules are properly exported and recommended rules are defined correctly. * Condenses imports. * Sets default recommended value. * replace Object.hasOwn for node 14 Co-authored-by: JJ Kasper --- package.json | 1 + .../lib/rules/no-title-in-document-head.js | 1 + pnpm-lock.yaml | 131 ++++++++++++++++++ test/jest-setup-after-env.ts | 3 + test/jest.d.ts | 1 + test/unit/eslint-plugin-next/index.test.ts | 28 ++++ tsconfig.json | 1 + 7 files changed, 166 insertions(+) create mode 100644 test/jest.d.ts create mode 100644 test/unit/eslint-plugin-next/index.test.ts diff --git a/package.json b/package.json index 5dc21b564b..9a202877a9 100644 --- a/package.json +++ b/package.json @@ -144,6 +144,7 @@ "is-animated": "2.0.2", "isomorphic-unfetch": "3.0.0", "jest": "27.0.6", + "jest-extended": "1.2.1", "ky": "0.19.1", "ky-universal": "0.6.0", "lerna": "4.0.0", diff --git a/packages/eslint-plugin-next/lib/rules/no-title-in-document-head.js b/packages/eslint-plugin-next/lib/rules/no-title-in-document-head.js index f2eb7d162b..1bd3664dab 100644 --- a/packages/eslint-plugin-next/lib/rules/no-title-in-document-head.js +++ b/packages/eslint-plugin-next/lib/rules/no-title-in-document-head.js @@ -5,6 +5,7 @@ module.exports = { docs: { description: 'Prevent usage of `` with `Head` component from `next/document`.', + recommended: true, url, }, }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c4893a6841..34b39f0b37 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -109,6 +109,7 @@ importers: is-animated: 2.0.2 isomorphic-unfetch: 3.0.0 jest: 27.0.6 + jest-extended: 1.2.1 ky: 0.19.1 ky-universal: 0.6.0 lerna: 4.0.0 @@ -260,6 +261,7 @@ importers: is-animated: 2.0.2 isomorphic-unfetch: 3.0.0 jest: 27.0.6_node-notifier@8.0.1 + jest-extended: 1.2.1 ky: 0.19.1 ky-universal: 0.6.0_ky@0.19.1 lerna: 4.0.0 @@ -3836,6 +3838,17 @@ packages: - supports-color dev: true + /@jest/types/26.6.2: + resolution: {integrity: sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==} + engines: {node: '>= 10.14.2'} + dependencies: + '@types/istanbul-lib-coverage': 2.0.3 + '@types/istanbul-reports': 3.0.0 + '@types/node': 17.0.21 + '@types/yargs': 15.0.14 + chalk: 4.1.2 + dev: true + /@jest/types/27.0.6: resolution: {integrity: sha512-aSquT1qa9Pik26JK5/3rvnYb4bGtm1VFNesHKmNTwmPIgOrixvhL2ghIvFRNEpzy3gU+rUgjIF/KodbkFAl++g==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -5969,6 +5982,12 @@ packages: resolution: {integrity: sha512-gCubfBUZ6KxzoibJ+SCUc/57Ms1jz5NjHe4+dI2krNmU5zCPAphyLJYyTOg06ueIyfj+SaCUqmzun7ImlxDcKg==} dev: true + /@types/yargs/15.0.14: + resolution: {integrity: sha512-yEJzHoxf6SyQGhBhIYGXQDSCkJjB6HohDShto7m8vaKg9Yp0Yn8+71J9eakh2bnPg6BfsH9PRMhiRTZnd4eXGQ==} + dependencies: + '@types/yargs-parser': 13.1.0 + dev: true + /@types/yargs/16.0.0: resolution: {integrity: sha512-2nN6AGeMwe8+O6nO9ytQfbMQOJy65oi1yK2y/9oReR08DaXSGtMsrLyCM1ooKqfICpCx4oITaR4LkOmdzz41Ww==} dependencies: @@ -9667,11 +9686,21 @@ packages: streamsearch: 0.1.2 dev: true + /diff-sequences/26.6.2: + resolution: {integrity: sha512-Mv/TDa3nZ9sbc5soK+OoA74BsS3mL37yixCvUAQkiuA4Wz6YtwP/K47n2rv2ovzHZvoiQeA5FTQOschKkEwB0Q==} + engines: {node: '>= 10.14.2'} + dev: true + /diff-sequences/27.0.6: resolution: {integrity: sha512-ag6wfpBFyNXZ0p8pcuIDS//D8H062ZQJ3fzYxjpmeKjnz8W4pekL3AI8VohmyZmsWW2PWaHgjsmqR6L13101VQ==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dev: true + /diff-sequences/27.5.1: + resolution: {integrity: sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + dev: true + /diffie-hellman/5.0.3: resolution: {integrity: sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==} dependencies: @@ -10771,6 +10800,18 @@ packages: homedir-polyfill: 1.0.3 dev: true + /expect/26.6.2: + resolution: {integrity: sha512-9/hlOBkQl2l/PLHJx6JjoDF6xPKcJEsUlWKb23rKE7KzeDqUZKXKNMW27KIue5JMdBV9HgmoJPcc8HtO85t9IA==} + engines: {node: '>= 10.14.2'} + dependencies: + '@jest/types': 26.6.2 + ansi-styles: 4.3.0 + jest-get-type: 26.3.0 + jest-matcher-utils: 26.6.2 + jest-message-util: 26.6.2 + jest-regex-util: 26.0.0 + dev: true + /expect/27.0.6: resolution: {integrity: sha512-psNLt8j2kwg42jGBDSfAlU49CEZxejN1f1PlANWDZqIhBOVU/c2Pm888FcjWJzFewhIsNWfZJeLjUjtKGiPuSw==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -13488,6 +13529,16 @@ packages: - utf-8-validate dev: true + /jest-diff/26.6.2: + resolution: {integrity: sha512-6m+9Z3Gv9wN0WFVasqjCL/06+EFCMTqDEUl/b87HYK2rAPTyfz4ZIuSlPhY51PIQRWx5TaxeF1qmXKe9gfN3sA==} + engines: {node: '>= 10.14.2'} + dependencies: + chalk: 4.1.2 + diff-sequences: 26.6.2 + jest-get-type: 26.3.0 + pretty-format: 26.6.2 + dev: true + /jest-diff/27.0.6: resolution: {integrity: sha512-Z1mqgkTCSYaFgwTlP/NUiRzdqgxmmhzHY1Tq17zL94morOHfHu3K4bgSgl+CR4GLhpV8VxkuOYuIWnQ9LnFqmg==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -13498,6 +13549,16 @@ packages: pretty-format: 27.5.1 dev: true + /jest-diff/27.5.1: + resolution: {integrity: sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + dependencies: + chalk: 4.1.2 + diff-sequences: 27.5.1 + jest-get-type: 27.5.1 + pretty-format: 27.5.1 + dev: true + /jest-docblock/27.0.6: resolution: {integrity: sha512-Fid6dPcjwepTFraz0YxIMCi7dejjJ/KL9FBjPYhBp4Sv1Y9PdhImlKZqYU555BlN4TQKaTc+F2Av1z+anVyGkA==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -13546,11 +13607,31 @@ packages: jest-util: 27.0.6 dev: true + /jest-extended/1.2.1: + resolution: {integrity: sha512-eKZR5iDpyTkcDesj16FpIPnjAWQNUB81ZFQW08EIddM6iqO7DjRIi39td9qol+1dpJS4Mqr9Qzp8ZMhanbSeug==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + dependencies: + expect: 26.6.2 + jest-diff: 27.5.1 + jest-get-type: 27.0.6 + jest-matcher-utils: 27.5.1 + dev: true + + /jest-get-type/26.3.0: + resolution: {integrity: sha512-TpfaviN1R2pQWkIihlfEanwOXK0zcxrKEE4MlU6Tn7keoXdN6/3gK/xl0yEh8DOunn5pOVGKf8hB4R9gVh04ig==} + engines: {node: '>= 10.14.2'} + dev: true + /jest-get-type/27.0.6: resolution: {integrity: sha512-XTkK5exIeUbbveehcSR8w0bhH+c0yloW/Wpl+9vZrjzztCPWrxhHwkIFpZzCt71oRBsgxmuUfxEqOYoZI2macg==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dev: true + /jest-get-type/27.5.1: + resolution: {integrity: sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + dev: true + /jest-haste-map/27.0.6: resolution: {integrity: sha512-4ldjPXX9h8doB2JlRzg9oAZ2p6/GpQUNAeiYXqcpmrKbP0Qev0wdZlxSMOmz8mPOEnt4h6qIzXFLDi8RScX/1w==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -13605,6 +13686,16 @@ packages: pretty-format: 27.5.1 dev: true + /jest-matcher-utils/26.6.2: + resolution: {integrity: sha512-llnc8vQgYcNqDrqRDXWwMr9i7rS5XFiCwvh6DTP7Jqa2mqpcCBBlpCbn+trkG0KNhPu/h8rzyBkriOtBstvWhw==} + engines: {node: '>= 10.14.2'} + dependencies: + chalk: 4.1.2 + jest-diff: 26.6.2 + jest-get-type: 26.3.0 + pretty-format: 26.6.2 + dev: true + /jest-matcher-utils/27.0.6: resolution: {integrity: sha512-OFgF2VCQx9vdPSYTHWJ9MzFCehs20TsyFi6bIHbk5V1u52zJOnvF0Y/65z3GLZHKRuTgVPY4Z6LVePNahaQ+tA==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -13615,6 +13706,31 @@ packages: pretty-format: 27.5.1 dev: true + /jest-matcher-utils/27.5.1: + resolution: {integrity: sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + dependencies: + chalk: 4.1.2 + jest-diff: 27.5.1 + jest-get-type: 27.5.1 + pretty-format: 27.5.1 + dev: true + + /jest-message-util/26.6.2: + resolution: {integrity: sha512-rGiLePzQ3AzwUshu2+Rn+UMFk0pHN58sOG+IaJbk5Jxuqo3NYO1U2/MIR4S1sKgsoYSXSzdtSa0TgrmtUwEbmA==} + engines: {node: '>= 10.14.2'} + dependencies: + '@babel/code-frame': 7.16.7 + '@jest/types': 26.6.2 + '@types/stack-utils': 2.0.0 + chalk: 4.1.2 + graceful-fs: 4.2.9 + micromatch: 4.0.4 + pretty-format: 26.6.2 + slash: 3.0.0 + stack-utils: 2.0.3 + dev: true + /jest-message-util/27.0.6: resolution: {integrity: sha512-rBxIs2XK7rGy+zGxgi+UJKP6WqQ+KrBbD1YMj517HYN3v2BG66t3Xan3FWqYHKZwjdB700KiAJ+iES9a0M+ixw==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -13673,6 +13789,11 @@ packages: jest-resolve: 27.0.6 dev: true + /jest-regex-util/26.0.0: + resolution: {integrity: sha512-Gv3ZIs/nA48/Zvjrl34bf+oD76JHiGDUxNOVgUjh3j890sblXryjY4rss71fPtD/njchl6PSE2hIhvyWa1eT0A==} + engines: {node: '>= 10.14.2'} + dev: true + /jest-regex-util/27.0.6: resolution: {integrity: sha512-SUhPzBsGa1IKm8hx2F4NfTGGp+r7BXJ4CulsZ1k2kI+mGLG+lxGrs76veN2LF/aUdGosJBzKgXmNCw+BzFqBDQ==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -17965,6 +18086,16 @@ packages: engines: {node: '>=6'} dev: true + /pretty-format/26.6.2: + resolution: {integrity: sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==} + engines: {node: '>= 10'} + dependencies: + '@jest/types': 26.6.2 + ansi-regex: 5.0.1 + ansi-styles: 4.3.0 + react-is: 17.0.2 + dev: true + /pretty-format/27.5.1: resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} diff --git a/test/jest-setup-after-env.ts b/test/jest-setup-after-env.ts index 86cc1a8e33..6d024d77b4 100644 --- a/test/jest-setup-after-env.ts +++ b/test/jest-setup-after-env.ts @@ -1,3 +1,6 @@ +import * as matchers from 'jest-extended' +expect.extend(matchers) + // A default max-timeout of 90 seconds is allowed // per test we should aim to bring this down though jest.setTimeout((process.platform === 'win32' ? 180 : 90) * 1000) diff --git a/test/jest.d.ts b/test/jest.d.ts new file mode 100644 index 0000000000..b68ae07700 --- /dev/null +++ b/test/jest.d.ts @@ -0,0 +1 @@ +import 'jest-extended' diff --git a/test/unit/eslint-plugin-next/index.test.ts b/test/unit/eslint-plugin-next/index.test.ts new file mode 100644 index 0000000000..394d2a3748 --- /dev/null +++ b/test/unit/eslint-plugin-next/index.test.ts @@ -0,0 +1,28 @@ +import { basename } from 'path' +import glob from 'glob' +import index from '@next/eslint-plugin-next' + +const getRuleNameFromRulePath = (path) => basename(path, '.js') +const rulePaths = glob.sync('packages/eslint-plugin-next/lib/rules/*js', { + absolute: true, +}) + +describe('@next/eslint-plugin-next index', () => { + it('should include all defined rules and no extra / undefined rules', () => { + const rules = rulePaths.map((rulePath) => getRuleNameFromRulePath(rulePath)) + + expect(index.rules).toContainAllKeys(rules) + }) + + rulePaths.forEach((rulePath) => { + const rule = require(rulePath) + const ruleName = getRuleNameFromRulePath(rulePath) + const { recommended = false } = rule.meta.docs + + it(`${ruleName}: recommend should be \`${recommended}\``, () => { + expect(`@next/next/${ruleName}` in index.configs.recommended.rules).toBe( + recommended + ) + }) + }) +}) diff --git a/tsconfig.json b/tsconfig.json index 8609c1ea78..6323ec1c65 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -18,6 +18,7 @@ } }, "include": [ + "test/jest.d.ts", "test/**/*.test.ts", "test/**/*.test.tsx", "test/**/test/*",