diff --git a/.flowconfig b/.flowconfig index 46e35fd4e..e01587181 100644 --- a/.flowconfig +++ b/.flowconfig @@ -3,5 +3,6 @@ /lib/.* /docs/.* /reports/.* +/examples/.* [options] suppress_type=$FlowFixMe diff --git a/.github/workflows/node-4+.yml b/.github/workflows/node-4+.yml index d5c908cab..fba82fd3b 100644 --- a/.github/workflows/node-4+.yml +++ b/.github/workflows/node-4+.yml @@ -25,6 +25,7 @@ jobs: matrix: node-version: ${{ fromJson(needs.matrix.outputs.latest) }} eslint: + - 9 - 8 - 7 - 6 @@ -32,6 +33,32 @@ jobs: - 4 - 3 exclude: + - node-version: 16 + eslint: 9 + - node-version: 15 + eslint: 9 + - node-version: 14 + eslint: 9 + - node-version: 13 + eslint: 9 + - node-version: 12 + eslint: 9 + - node-version: 11 + eslint: 9 + - node-version: 10 + eslint: 9 + - node-version: 9 + eslint: 9 + - node-version: 8 + eslint: 9 + - node-version: 7 + eslint: 9 + - node-version: 6 + eslint: 9 + - node-version: 5 + eslint: 9 + - node-version: 4 + eslint: 9 - node-version: 15 eslint: 8 - node-version: 13 @@ -90,7 +117,7 @@ jobs: steps: - uses: actions/checkout@v4 with: - fetch-depth: 0 + fetch-depth: 0 - uses: ljharb/actions/node/install@main name: 'nvm install ${{ matrix.node-version }} && npm install' env: @@ -101,7 +128,7 @@ jobs: skip-ls-check: true - run: rm __tests__/src/util/getComputedRole-test.js if: ${{ matrix.node-version < 7 }} - - run: npm run test:ci + - run: npm run tests-only - uses: codecov/codecov-action@v3.1.5 node: diff --git a/CHANGELOG.md b/CHANGELOG.md index b2004f23a..5cb0eaac9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,29 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [v6.10.0](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/compare/v6.9.0...v6.10.0) - 2024-09-03 + +### Fixed + +- [New] `label-has-associated-control`: add additional error message [`#1005`](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/issues/1005) +- [Fix] `label-has-associated-control`: ignore undetermined label text [`#966`](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/issues/966) + +### Commits + +- [Tests] switch from jest to tape [`a284cbf`](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/commit/a284cbf4eb21292c4cff87f02be0bfb82764757f) +- [New] add eslint 9 support [`deac4fd`](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/commit/deac4fd06eff4c0f5da27611c2a44a009b7e7fda) +- [New] add `attributes` setting [`a1ee7f8`](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/commit/a1ee7f8810efafe416eb5d7f6eb0505b52873495) +- [New] allow polymorphic linting to be restricted [`6cd1a70`](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/commit/6cd1a7011446e3925f2b49c51ff26246a21491d1) +- [Tests] remove duplicate tests [`74d5dec`](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/commit/74d5decb6f2e42c05ce40a45630041fd695a2e7f) +- [Dev Deps] update `@babel/cli`, `@babel/core`, `@babel/eslint-parser`, `@babel/plugin-transform-flow-strip-types` [`6eca235`](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/commit/6eca2359f5457af72dbfba265b73297c9232cb3e) +- [readme] remove deprecated travis ci badge; add github actions badge [`0be7ea9`](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/commit/0be7ea95f560c6afc6817d381054d914ebd0b2ca) +- [Tests] use `npm audit` instead of `aud` [`05a5e49`](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/commit/05a5e4992900e0d5d61e29e13046c90797b68a7c) +- [Deps] update `axobject-query` [`912e98c`](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/commit/912e98c425ef9fcc2d7d22b45b4f7e3b445112a5) +- [Deps] unpin `axobject-query` [`75147aa`](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/commit/75147aa68888fc150a4efea5b99809969bdc32b2) +- [Deps] update `axe-core` [`27ff7cb`](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/commit/27ff7cbf562bf2685fd5a6062e58eb4727cb85c6) +- [readme] fix jsxA11y import name [`ce846e0`](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/commit/ce846e00414c41676a6a8601022059878bcc0b89) +- [readme] fix typo in shareable config section in readme [`cca288b`](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/commit/cca288b73a39fa0932a57c02a7a88de68fc971fc) + ## [v6.9.0](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/compare/v6.8.0...v6.9.0) - 2024-06-19 ### Fixed diff --git a/README.md b/README.md index 5f66a744c..e5119223a 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@

- - build status + + CI status path.basename(f, '.js')); -describe('all rule files should be exported by the plugin', () => { +test('all rule files should be exported by the plugin', (t) => { rules.forEach((ruleName) => { - it(`should export ${ruleName}`, () => { - expect(plugin.rules[ruleName]).toEqual( - require(path.join('../src/rules', ruleName)) // eslint-disable-line - ); - }); + t.equal( + plugin.rules[ruleName], + require(path.join('../src/rules', ruleName)), // eslint-disable-line import/no-dynamic-require + `exports ${ruleName}`, + ); }); + + t.end(); }); -describe('configurations', () => { - it('should export a \'recommended\' configuration', () => { - expect(plugin.configs.recommended).toBeDefined(); - }); +test('configurations', (t) => { + t.notEqual(plugin.configs.recommended, undefined, 'exports a \'recommended\' configuration'); + + t.end(); }); -describe('schemas', () => { +test('schemas', (t) => { rules.forEach((ruleName) => { - it(`${ruleName} should export a schema with type object`, () => { - const rule = require(path.join('../src/rules', ruleName)); // eslint-disable-line - const schema = rule.meta && rule.meta.schema && rule.meta.schema[0]; - const { type } = schema; + const rule = require(path.join('../src/rules', ruleName)); // eslint-disable-line import/no-dynamic-require + const schema = rule.meta && rule.meta.schema && rule.meta.schema[0]; + const { type } = schema; - expect(type).toEqual('object'); - }); + t.equal(type, 'object', `${ruleName} exports a schema with type object`); }); + + t.end(); }); diff --git a/__tests__/src/rules/anchor-ambiguous-text-test.js b/__tests__/src/rules/anchor-ambiguous-text-test.js index cbbc39501..12769d9ad 100644 --- a/__tests__/src/rules/anchor-ambiguous-text-test.js +++ b/__tests__/src/rules/anchor-ambiguous-text-test.js @@ -1,4 +1,3 @@ -/* eslint-env jest */ /** * @fileoverview Enforce `` text to not exactly match "click here", "here", "link", or "a link". * @author Matt Wang diff --git a/__tests__/src/rules/anchor-is-valid-test.js b/__tests__/src/rules/anchor-is-valid-test.js index 9fb4025e9..857605a15 100644 --- a/__tests__/src/rules/anchor-is-valid-test.js +++ b/__tests__/src/rules/anchor-is-valid-test.js @@ -272,14 +272,9 @@ ruleTester.run('anchor-is-valid', rule, { options: noHrefAspect, }, - // CUSTOM COMPONENTS AND SPECIALLINK AND ASPECT + // CUSTOM COMPONENTS AND SPECIAL LINK AND ASPECT { code: '', options: componentsAndSpecialLinkAndInvalidHrefAspect }, { code: '', options: componentsAndSpecialLinkAndInvalidHrefAspect }, - { code: '', options: componentsAndSpecialLinkAndInvalidHrefAspect }, - { code: '', options: componentsAndSpecialLinkAndInvalidHrefAspect }, - { code: '', options: componentsAndSpecialLinkAndInvalidHrefAspect }, - { code: '', options: componentsAndSpecialLinkAndInvalidHrefAspect }, - )).map(parserOptionsMapper), invalid: parsers.all([].concat( // DEFAULT ELEMENT 'a' TESTS @@ -372,7 +367,7 @@ ruleTester.run('anchor-is-valid', rule, { options: specialLink, }, - // CUSTOM BOTH COMPONENTS AND SPECIALLINK TESTS + // CUSTOM BOTH COMPONENTS AND SPECIAL LINK TESTS // NO HREF { code: '', errors: [noHrefexpectedError], options: componentsAndSpecialLink }, { code: '', errors: [noHrefexpectedError], options: componentsAndSpecialLink }, @@ -522,27 +517,7 @@ ruleTester.run('anchor-is-valid', rule, { errors: [invalidHrefexpectedError], }, - // CUSTOM COMPONENTS AND SPECIALLINK AND ASPECT - { - code: '', - options: componentsAndSpecialLinkAndNoHrefAspect, - errors: [noHrefexpectedError], - }, - { - code: '', - options: componentsAndSpecialLinkAndNoHrefAspect, - errors: [noHrefexpectedError], - }, - { - code: '', - options: componentsAndSpecialLinkAndNoHrefAspect, - errors: [noHrefexpectedError], - }, - { - code: '', - options: componentsAndSpecialLinkAndNoHrefAspect, - errors: [noHrefexpectedError], - }, + // CUSTOM COMPONENTS AND SPECIAL LINK AND ASPECT { code: '', options: componentsAndSpecialLinkAndNoHrefAspect, diff --git a/__tests__/src/rules/aria-proptypes-test.js b/__tests__/src/rules/aria-proptypes-test.js index 67be3304a..851cd7b30 100644 --- a/__tests__/src/rules/aria-proptypes-test.js +++ b/__tests__/src/rules/aria-proptypes-test.js @@ -9,7 +9,8 @@ import { aria } from 'aria-query'; import { RuleTester } from 'eslint'; -import expect from 'expect'; +import test from 'tape'; + import parserOptionsMapper from '../../__util__/parserOptionsMapper'; import parsers from '../../__util__/helpers/parsers'; import rule from '../../../src/rules/aria-proptypes'; @@ -51,13 +52,14 @@ tokens from the following: ${permittedValues}.`, } }; -describe('validityCheck', () => { - it('should false for an unknown expected type', () => { - expect(validityCheck( - null, - null, - )).toBe(false); - }); +test('validityCheck', (t) => { + t.equal( + validityCheck(null, null), + false, + 'is false for an unknown expected type', + ); + + t.end(); }); ruleTester.run('aria-proptypes', rule, { diff --git a/__tests__/src/rules/img-redundant-alt-test.js b/__tests__/src/rules/img-redundant-alt-test.js index 3bd5fcbbe..73bb14f02 100644 --- a/__tests__/src/rules/img-redundant-alt-test.js +++ b/__tests__/src/rules/img-redundant-alt-test.js @@ -67,8 +67,8 @@ ruleTester.run('img-redundant-alt', rule, { { code: '{imageAlt}' }, { code: '{imageAlt.name}' }, semver.satisfies(eslintVersion, '>= 6') ? [ - { code: '{imageAlt?.name}', parserOptions: { ecmaVersion: 2020 } }, - { code: 'Doing cool things', parserOptions: { ecmaVersion: 2020 } }, + { code: '{imageAlt?.name}', languageOptions: { ecmaVersion: 2020 } }, + { code: 'Doing cool things', languageOptions: { ecmaVersion: 2020 } }, ] : [], { code: 'Photography;' }, { code: 'ImageMagick;' }, diff --git a/__tests__/src/rules/label-has-associated-control-test.js b/__tests__/src/rules/label-has-associated-control-test.js index d0b4c3b31..6db067394 100644 --- a/__tests__/src/rules/label-has-associated-control-test.js +++ b/__tests__/src/rules/label-has-associated-control-test.js @@ -26,6 +26,11 @@ const expectedError = { type: 'JSXOpeningElement', }; +const expectedErrorNoLabel = { + message: 'A form label must have accessible text.', + type: 'JSXOpeningElement', +}; + const componentsSettings = { 'jsx-a11y': { components: { @@ -35,11 +40,23 @@ const componentsSettings = { }, }; +const attributesSettings = { + 'jsx-a11y': { + attributes: { + for: ['htmlFor', 'for'], + }, + }, +}; + const htmlForValid = [ { code: '', options: [{ depth: 4 }] }, { code: '

' }, + { code: '', options: [{ depth: 4 }], settings: attributesSettings }, + { code: '